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