1 | /* sigset_SIG_HOLD_bug.c [BZ #1951] */ |
2 | #include <errno.h> |
3 | #include <error.h> |
4 | #include <inttypes.h> |
5 | #include <signal.h> |
6 | #include <stdio.h> |
7 | #include <stdlib.h> |
8 | #include <string.h> |
9 | #include <unistd.h> |
10 | #include <sys/types.h> |
11 | #include <sys/wait.h> |
12 | #include <libc-diag.h> |
13 | |
14 | /* The sigset function is deprecated. */ |
15 | DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations" ); |
16 | |
17 | #define TEST_SIG SIGINT |
18 | |
19 | |
20 | /* Print mask of blocked signals for this process */ |
21 | static void |
22 | printSigMask (const char *msg) |
23 | { |
24 | sigset_t currMask; |
25 | int sig; |
26 | int cnt; |
27 | |
28 | if (msg != NULL) |
29 | printf (format: "%s" , msg); |
30 | |
31 | if (sigprocmask (SIG_BLOCK, NULL, oset: &currMask) == -1) |
32 | error (status: 1, errno, format: "sigaction" ); |
33 | |
34 | cnt = 0; |
35 | for (sig = 1; sig < NSIG; sig++) |
36 | { |
37 | if (sigismember (&currMask, sig)) |
38 | { |
39 | cnt++; |
40 | printf (format: "\t\t%d (%s)\n" , sig, strsignal (sig: sig)); |
41 | } |
42 | } |
43 | |
44 | if (cnt == 0) |
45 | printf (format: "\t\t<empty signal set>\n" ); |
46 | } /* printSigMask */ |
47 | |
48 | static void |
49 | handler (int sig) |
50 | { |
51 | printf (format: "Caught signal %d\n" , sig); |
52 | printSigMask (msg: "Signal mask in handler\n" ); |
53 | printf (format: "Handler returning\n" ); |
54 | _exit (1); |
55 | } /* handler */ |
56 | |
57 | static void |
58 | printDisposition (sighandler_t disp) |
59 | { |
60 | if (disp == SIG_HOLD) |
61 | printf (format: "SIG_HOLD" ); |
62 | else if (disp == SIG_DFL) |
63 | printf (format: "SIG_DFL" ); |
64 | else if (disp == SIG_IGN) |
65 | printf (format: "SIG_IGN" ); |
66 | else |
67 | printf (format: "handled at %" PRIxPTR, (uintptr_t) disp); |
68 | } /* printDisposition */ |
69 | |
70 | static int |
71 | returnTest1 (void) |
72 | { |
73 | sighandler_t prev; |
74 | |
75 | printf (format: "===== TEST 1 =====\n" ); |
76 | printf (format: "Blocking signal with sighold()\n" ); |
77 | if (sighold (TEST_SIG) == -1) |
78 | error (status: 1, errno, format: "sighold" ); |
79 | printSigMask (msg: "Signal mask after sighold()\n" ); |
80 | |
81 | printf (format: "About to use sigset() to establish handler\n" ); |
82 | prev = sigset (TEST_SIG, disp: handler); |
83 | if (prev == SIG_ERR) |
84 | error(status: 1, errno, format: "sigset" ); |
85 | |
86 | printf (format: "Previous disposition: " ); |
87 | printDisposition (disp: prev); |
88 | printf (format: " (should be SIG_HOLD)\n" ); |
89 | if (prev != SIG_HOLD) |
90 | { |
91 | printf(format: "TEST FAILED!!!\n" ); |
92 | return 1; |
93 | } |
94 | return 0; |
95 | } /* returnTest1 */ |
96 | |
97 | static int |
98 | returnTest2 (void) |
99 | { |
100 | sighandler_t prev; |
101 | |
102 | printf (format: "\n===== TEST 2 =====\n" ); |
103 | |
104 | printf (format: "About to use sigset() to set SIG_HOLD\n" ); |
105 | prev = sigset (TEST_SIG, SIG_HOLD); |
106 | if (prev == SIG_ERR) |
107 | error (status: 1, errno, format: "sigset" ); |
108 | |
109 | printf (format: "Previous disposition: " ); |
110 | printDisposition (disp: prev); |
111 | printf (format: " (should be SIG_DFL)\n" ); |
112 | if (prev != SIG_DFL) |
113 | { |
114 | printf(format: "TEST FAILED!!!\n" ); |
115 | return 1; |
116 | } |
117 | return 0; |
118 | } /* returnTest2 */ |
119 | |
120 | static int |
121 | returnTest3 (void) |
122 | { |
123 | sighandler_t prev; |
124 | |
125 | printf (format: "\n===== TEST 3 =====\n" ); |
126 | |
127 | printf (format: "About to use sigset() to set SIG_HOLD\n" ); |
128 | prev = sigset (TEST_SIG, SIG_HOLD); |
129 | if (prev == SIG_ERR) |
130 | error (status: 1, errno, format: "sigset" ); |
131 | |
132 | printf (format: "About to use sigset() to set SIG_HOLD (again)\n" ); |
133 | prev = sigset (TEST_SIG, SIG_HOLD); |
134 | if (prev == SIG_ERR) |
135 | error (status: 1, errno, format: "sigset" ); |
136 | |
137 | printf (format: "Previous disposition: " ); |
138 | printDisposition (disp: prev); |
139 | printf (format: " (should be SIG_HOLD)\n" ); |
140 | if (prev != SIG_HOLD) |
141 | { |
142 | printf(format: "TEST FAILED!!!\n" ); |
143 | return 1; |
144 | } |
145 | return 0; |
146 | } /* returnTest3 */ |
147 | |
148 | int |
149 | main (int argc, char *argv[]) |
150 | { |
151 | pid_t childPid; |
152 | |
153 | childPid = fork(); |
154 | if (childPid == -1) |
155 | error (status: 1, errno, format: "fork" ); |
156 | |
157 | if (childPid == 0) |
158 | exit (returnTest1 ()); |
159 | |
160 | int status; |
161 | if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid) |
162 | error (status: 1, errno, format: "waitpid" ); |
163 | int result = !WIFEXITED (status) || WEXITSTATUS (status) != 0; |
164 | |
165 | childPid = fork(); |
166 | if (childPid == -1) |
167 | error (status: 1, errno, format: "fork" ); |
168 | |
169 | if (childPid == 0) |
170 | exit (returnTest2 ()); |
171 | |
172 | if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid) |
173 | error (status: 1, errno, format: "waitpid" ); |
174 | result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0; |
175 | |
176 | childPid = fork(); |
177 | if (childPid == -1) |
178 | error (status: 1, errno, format: "fork" ); |
179 | |
180 | if (childPid == 0) |
181 | exit (returnTest3 ()); |
182 | |
183 | if (TEMP_FAILURE_RETRY (waitpid (childPid, &status, 0)) != childPid) |
184 | error (status: 1, errno, format: "waitpid" ); |
185 | result |= !WIFEXITED (status) || WEXITSTATUS (status) != 0; |
186 | |
187 | return result; |
188 | } /* main */ |
189 | |