Commit | Line | Data |
---|---|---|
2af6d46f PA |
1 | /* Self tests for scoped_ignored_signal for GDB, the GNU debugger. |
2 | ||
3 | Copyright (C) 2021 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "gdbsupport/scoped_ignore_signal.h" | |
22 | #include "gdbsupport/selftest.h" | |
23 | #include "gdbsupport/scope-exit.h" | |
24 | #include <unistd.h> | |
25 | #include <signal.h> | |
26 | ||
27 | namespace selftests { | |
28 | namespace scoped_ignore_sig { | |
29 | ||
30 | #ifdef SIGPIPE | |
31 | ||
32 | /* True if the SIGPIPE handler ran. */ | |
33 | static volatile sig_atomic_t got_sigpipe = 0; | |
34 | ||
35 | /* SIGPIPE handler for testing. */ | |
36 | ||
37 | static void | |
38 | handle_sigpipe (int) | |
39 | { | |
40 | got_sigpipe = 1; | |
41 | } | |
42 | ||
43 | /* Test scoped_ignore_sigpipe. */ | |
44 | ||
45 | static void | |
46 | test_sigpipe () | |
47 | { | |
48 | auto *osig = signal (SIGPIPE, handle_sigpipe); | |
49 | SCOPE_EXIT { signal (SIGPIPE, osig); }; | |
50 | ||
51 | #ifdef HAVE_SIGPROCMASK | |
52 | /* Make sure SIGPIPE isn't blocked. */ | |
53 | sigset_t set, old_state; | |
54 | sigemptyset (&set); | |
55 | sigaddset (&set, SIGPIPE); | |
56 | sigprocmask (SIG_UNBLOCK, &set, &old_state); | |
57 | SCOPE_EXIT { sigprocmask (SIG_SETMASK, &old_state, nullptr); }; | |
58 | #endif | |
59 | ||
60 | /* Create pipe, and close read end so that writes to the pipe fail | |
61 | with EPIPE. */ | |
62 | ||
63 | int fd[2]; | |
64 | char c = 0xff; | |
65 | int r; | |
66 | ||
67 | r = pipe (fd); | |
68 | SELF_CHECK (r == 0); | |
69 | ||
70 | close (fd[0]); | |
71 | SCOPE_EXIT { close (fd[1]); }; | |
72 | ||
73 | /* Check that writing to the pipe results in EPIPE. EXPECT_SIG | |
74 | indicates whether a SIGPIPE signal is expected. */ | |
75 | auto check_pipe_write = [&] (bool expect_sig) | |
76 | { | |
77 | got_sigpipe = 0; | |
78 | errno = 0; | |
79 | ||
80 | r = write (fd[1], &c, 1); | |
81 | SELF_CHECK (r == -1 && errno == EPIPE | |
82 | && got_sigpipe == expect_sig); | |
83 | }; | |
84 | ||
85 | /* Check that without a scoped_ignore_sigpipe in scope we indeed get | |
86 | a SIGPIPE signal. */ | |
87 | check_pipe_write (true); | |
88 | ||
89 | /* Now check that with a scoped_ignore_sigpipe in scope, SIGPIPE is | |
90 | ignored/blocked. */ | |
91 | { | |
92 | scoped_ignore_sigpipe ignore1; | |
93 | ||
94 | check_pipe_write (false); | |
95 | ||
96 | /* Check that scoped_ignore_sigpipe nests correctly. */ | |
97 | { | |
98 | scoped_ignore_sigpipe ignore2; | |
99 | ||
100 | check_pipe_write (false); | |
101 | } | |
102 | ||
103 | /* If nesting works correctly, this write results in no | |
104 | SIGPIPE. */ | |
105 | check_pipe_write (false); | |
106 | } | |
107 | ||
108 | /* No scoped_ignore_sigpipe is in scope anymore, so this should | |
109 | result in a SIGPIPE signal. */ | |
110 | check_pipe_write (true); | |
111 | } | |
112 | ||
113 | #endif /* SIGPIPE */ | |
114 | ||
115 | } /* namespace scoped_ignore_sig */ | |
116 | } /* namespace selftests */ | |
117 | ||
118 | void _initialize_scoped_ignore_signal_selftests (); | |
119 | void | |
120 | _initialize_scoped_ignore_signal_selftests () | |
121 | { | |
122 | #ifdef SIGPIPE | |
123 | selftests::register_test ("scoped_ignore_sigpipe", | |
124 | selftests::scoped_ignore_sig::test_sigpipe); | |
125 | #endif | |
126 | } |