2004-06-19 Roland McGrath <roland@redhat.com>
[platform/upstream/glibc.git] / posix / tst-waitid.c
1 /* Tests for waitid.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <error.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26
27 #define TIMEOUT 15
28
29 static void
30 test_child (void)
31 {
32   /* First thing, we stop ourselves.  */
33   raise (SIGSTOP);
34
35   /* Hey, we got continued!  */
36   while (1)
37     pause ();
38 }
39
40 #ifndef WEXITED
41 # define WEXITED        0
42 # define WCONTINUED     0
43 # define WSTOPPED       WUNTRACED
44 #endif
45
46 static int
47 do_test (int argc, char *argv[])
48 {
49   pid_t pid = fork ();
50   if (pid < 0)
51     {
52       error (0, errno, "fork");
53       return EXIT_FAILURE;
54     }
55   else if (pid == 0)
56     {
57       test_child ();
58       _exit (127);
59     }
60
61   /* Give the child a chance to stop.  */
62   sleep (2);
63
64   /* Now try a wait that should not succeed.  */
65   siginfo_t info;
66   info.si_signo = 0;            /* A successful call sets it to SIGCHLD.  */
67   int fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG);
68   switch (fail)
69     {
70     default:
71       error (0, 0, "waitid returned bogus value %d\n", fail);
72       return EXIT_FAILURE;
73     case -1:
74       error (0, errno, "waitid WNOHANG on stopped");
75       return errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE;
76     case 0:
77       if (info.si_signo == 0)
78         break;
79       if (info.si_signo == SIGCHLD)
80         error (0, 0, "waitid WNOHANG on stopped status %d\n", info.si_status);
81       else
82         error (0, 0, "waitid WNOHANG on stopped signal %d\n", info.si_signo);
83       return EXIT_FAILURE;
84     }
85
86   /* Next the wait that should succeed right away.  */
87   info.si_signo = 0;            /* A successful call sets it to SIGCHLD.  */
88   info.si_pid = -1;
89   info.si_status = -1;
90   fail = waitid (P_PID, pid, &info, WSTOPPED|WNOHANG);
91   switch (fail)
92     {
93     default:
94       error (0, 0, "waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
95       return EXIT_FAILURE;
96     case -1:
97       error (0, errno, "waitid WSTOPPED|WNOHANG on stopped");
98       return errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE;
99     case 0:
100       if (info.si_signo != SIGCHLD)
101         {
102           error (0, 0, "waitid WSTOPPED|WNOHANG on stopped signal %d\n",
103                  info.si_signo);
104           return EXIT_FAILURE;
105         }
106       if (info.si_code != CLD_STOPPED)
107         {
108           error (0, 0, "waitid WSTOPPED|WNOHANG on stopped code %d\n",
109                  info.si_code);
110           return EXIT_FAILURE;
111         }
112       if (info.si_status != SIGSTOP)
113         {
114           error (0, 0, "waitid WSTOPPED|WNOHANG on stopped status %d\n",
115                  info.si_status);
116           return EXIT_FAILURE;
117         }
118       if (info.si_pid != pid)
119         {
120           error (0, 0, "waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
121                  info.si_pid, pid);
122           return EXIT_FAILURE;
123         }
124     }
125
126   if (kill (pid, SIGCONT) != 0)
127     {
128       error (0, errno, "kill (%d, SIGCONT)", pid);
129       return EXIT_FAILURE;
130     }
131
132   /* Wait for the child to have continued.  */
133   sleep (2);
134
135 #if 0
136   info.si_signo = 0;            /* A successful call sets it to SIGCHLD.  */
137   info.si_pid = -1;
138   info.si_status = -1;
139   fail = waitid (P_PID, pid, &info, WCONTINUED);
140   switch (fail)
141     {
142     default:
143       error (0, 0, "waitid WCONTINUED returned bogus value %d\n", fail);
144       return EXIT_FAILURE;
145     case -1:
146       error (0, errno, "waitid WCONTINUED on continued");
147       return errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE;
148     case 0:
149       if (info.si_signo != SIGCHLD)
150         {
151           error (0, 0, "waitid WCONTINUED on continued signal %d\n",
152                  info.si_signo);
153           return EXIT_FAILURE;
154         }
155       if (info.si_code != CLD_CONTINUED)
156         {
157           error (0, 0, "waitid WCONTINUED on continued code %d\n",
158                  info.si_code);
159           return EXIT_FAILURE;
160         }
161       if (info.si_status != SIGCONT)
162         {
163           error (0, 0, "waitid WCONTINUED on continued status %d\n",
164                  info.si_status);
165           return EXIT_FAILURE;
166         }
167       if (info.si_pid != pid)
168         {
169           error (0, 0, "waitid WCONTINUED on continued pid %d != %d\n",
170                  info.si_pid, pid);
171           return EXIT_FAILURE;
172         }
173     }
174 #endif
175
176   /* Die, child, die!  */
177   if (kill (pid, SIGKILL) != 0)
178     {
179       error (0, errno, "kill (%d, SIGKILL)", pid);
180       return EXIT_FAILURE;
181     }
182
183 #ifdef WNOWAIT
184   info.si_signo = 0;            /* A successful call sets it to SIGCHLD.  */
185   info.si_pid = -1;
186   info.si_status = -1;
187   fail = waitid (P_PID, pid, &info, WEXITED|WNOWAIT);
188   switch (fail)
189     {
190     default:
191       error (0, 0, "waitid WNOWAIT returned bogus value %d\n", fail);
192       return EXIT_FAILURE;
193     case -1:
194       error (0, errno, "waitid WNOWAIT on killed");
195       return errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE;
196     case 0:
197       if (info.si_signo != SIGCHLD)
198         {
199           error (0, 0, "waitid WNOWAIT on killed signal %d\n",
200                  info.si_signo);
201           return EXIT_FAILURE;
202         }
203       if (info.si_code != CLD_KILLED)
204         {
205           error (0, 0, "waitid WNOWAIT on killed code %d\n",
206                  info.si_code);
207           return EXIT_FAILURE;
208         }
209       if (info.si_status != SIGKILL)
210         {
211           error (0, 0, "waitid WNOWAIT on killed status %d\n",
212                  info.si_status);
213           return EXIT_FAILURE;
214         }
215       if (info.si_pid != pid)
216         {
217           error (0, 0, "waitid WNOWAIT on killed pid %d != %d\n",
218                  info.si_pid, pid);
219           return EXIT_FAILURE;
220         }
221     }
222 #else
223   /* Allow enough time to be sure the child died; we didn't synchronize.  */
224   sleep (2);
225 #endif
226
227   info.si_signo = 0;            /* A successful call sets it to SIGCHLD.  */
228   info.si_pid = -1;
229   info.si_status = -1;
230   fail = waitid (P_PID, pid, &info, WEXITED|WNOHANG);
231   switch (fail)
232     {
233     default:
234       error (0, 0, "waitid WNOHANG returned bogus value %d\n", fail);
235       return EXIT_FAILURE;
236     case -1:
237       error (0, errno, "waitid WNOHANG on killed");
238       return EXIT_FAILURE;
239     case 0:
240       if (info.si_signo != SIGCHLD)
241         {
242           error (0, 0, "waitid WNOHANG on killed signal %d\n",
243                  info.si_signo);
244           return EXIT_FAILURE;
245         }
246       if (info.si_code != CLD_KILLED)
247         {
248           error (0, 0, "waitid WNOHANG on killed code %d\n",
249                  info.si_code);
250           return EXIT_FAILURE;
251         }
252       if (info.si_status != SIGKILL)
253         {
254           error (0, 0, "waitid WNOHANG on killed status %d\n",
255                  info.si_status);
256           return EXIT_FAILURE;
257         }
258       if (info.si_pid != pid)
259         {
260           error (0, 0, "waitid WNOHANG on killed pid %d != %d\n",
261                  info.si_pid, pid);
262           return EXIT_FAILURE;
263         }
264     }
265
266   fail = waitid (P_PID, pid, &info, WEXITED);
267   if (fail == -1)
268     {
269       if (errno != ECHILD)
270         {
271           error (0, errno, "waitid WEXITED on killed");
272           return EXIT_FAILURE;
273         }
274     }
275   else
276     {
277       error (0, 0, "waitid WEXITED returned bogus value %d\n", fail);
278       return EXIT_FAILURE;
279     }
280
281   return EXIT_SUCCESS;
282 }
283
284 #include "../test-skeleton.c"