]>
Commit | Line | Data |
---|---|---|
8b9d6054 | 1 | /* Test for vfork functions. |
b168057a | 2 | Copyright (C) 2004-2015 Free Software Foundation, Inc. |
8b9d6054 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
8b9d6054 UD |
19 | |
20 | #include <errno.h> | |
21 | #include <signal.h> | |
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <time.h> | |
26 | #include <unistd.h> | |
27 | #include <sys/time.h> | |
28 | #include <sys/types.h> | |
29 | #include <sys/wait.h> | |
30 | ||
31 | int raise_fail; | |
32 | ||
33 | static void | |
34 | alrm (int sig) | |
35 | { | |
36 | if (raise (SIGUSR1) < 0) | |
37 | raise_fail = 1; | |
38 | } | |
39 | ||
40 | /* This test relies on non-POSIX functionality since the child | |
41 | processes call write, nanosleep and getpid. */ | |
42 | static int | |
43 | do_test (void) | |
44 | { | |
45 | int result = 0; | |
46 | int fd[2]; | |
47 | ||
48 | signal (SIGUSR1, SIG_IGN); | |
49 | ||
50 | struct sigaction sa; | |
51 | sa.sa_handler = alrm; | |
52 | sigemptyset (&sa.sa_mask); | |
53 | sa.sa_flags = 0; | |
54 | if (sigaction (SIGALRM, &sa, NULL) < 0) | |
55 | { | |
56 | puts ("couldn't set up SIGALRM handler"); | |
57 | return 1; | |
58 | } | |
59 | ||
60 | if (pipe (fd) == -1) | |
61 | { | |
62 | puts ("pipe failed"); | |
63 | return 1; | |
64 | } | |
65 | ||
66 | struct itimerval it; | |
67 | it.it_value.tv_sec = 0; | |
68 | it.it_value.tv_usec = 200 * 1000; | |
69 | it.it_interval = it.it_value; | |
70 | if (setitimer (ITIMER_REAL, &it, NULL) < 0) | |
71 | { | |
72 | puts ("couldn't set up timer"); | |
73 | return 1; | |
74 | } | |
75 | ||
76 | /* First vfork() without previous getpid(). */ | |
77 | pid_t p1; | |
78 | if ((p1 = vfork ()) == 0) | |
79 | { | |
80 | pid_t p = getpid (); | |
81 | ||
82 | struct timespec ts; | |
83 | ts.tv_sec = 1; | |
84 | ts.tv_nsec = 0; | |
85 | TEMP_FAILURE_RETRY (nanosleep (&ts, &ts)); | |
86 | _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p)); | |
87 | } | |
88 | else if (p1 == -1) | |
89 | { | |
90 | puts ("1st vfork failed"); | |
91 | result = 1; | |
92 | } | |
93 | ||
94 | memset (&it, 0, sizeof (it)); | |
95 | setitimer (ITIMER_REAL, &it, NULL); | |
96 | ||
97 | pid_t p2 = 0; | |
98 | if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t)) | |
99 | { | |
100 | puts ("1st read failed"); | |
101 | result = 1; | |
102 | } | |
103 | int r; | |
104 | if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1) | |
105 | { | |
106 | puts ("1st waitpid failed"); | |
107 | result = 1; | |
108 | } | |
109 | else if (r != 0) | |
110 | { | |
111 | puts ("write in 1st child failed"); | |
112 | result = 1; | |
113 | } | |
114 | ||
115 | /* Main process' ID. */ | |
116 | pid_t p0 = getpid (); | |
117 | ||
118 | /* vfork() again, but after a getpid() in the main process. */ | |
119 | pid_t p3; | |
120 | if ((p3 = vfork ()) == 0) | |
121 | { | |
122 | pid_t p = getpid (); | |
123 | _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p)); | |
124 | } | |
125 | else if (p1 == -1) | |
126 | { | |
127 | puts ("2nd vfork failed"); | |
128 | result = 1; | |
129 | } | |
130 | ||
131 | pid_t p4; | |
132 | if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t)) | |
133 | { | |
134 | puts ("2nd read failed"); | |
135 | result = 1; | |
136 | } | |
137 | if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3) | |
138 | { | |
139 | puts ("2nd waitpid failed"); | |
140 | result = 1; | |
141 | } | |
142 | else if (r != 0) | |
143 | { | |
144 | puts ("write in 2nd child failed"); | |
145 | result = 1; | |
146 | } | |
147 | ||
148 | /* And getpid in the main process again. */ | |
149 | pid_t p5 = getpid (); | |
150 | ||
151 | /* Analysis of the results. */ | |
152 | if (p0 != p5) | |
153 | { | |
154 | printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5); | |
155 | result = 1; | |
156 | } | |
157 | ||
158 | if (p0 == p1) | |
159 | { | |
160 | printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1); | |
161 | result = 1; | |
162 | } | |
163 | ||
164 | if (p1 != p2) | |
165 | { | |
166 | printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2); | |
167 | result = 1; | |
168 | } | |
169 | ||
170 | if (p0 == p3) | |
171 | { | |
172 | printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3); | |
173 | result = 1; | |
174 | } | |
175 | ||
176 | if (p3 != p4) | |
177 | { | |
178 | printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4); | |
179 | result = 1; | |
180 | } | |
181 | ||
182 | close (fd[0]); | |
183 | close (fd[1]); | |
184 | ||
185 | if (raise_fail) | |
186 | { | |
187 | puts ("raise failed"); | |
188 | result = 1; | |
189 | } | |
190 | ||
191 | if (result == 0) | |
192 | puts ("All OK"); | |
193 | ||
194 | return result; | |
195 | } | |
196 | ||
197 | #define TEST_FUNCTION do_test () | |
198 | #include "../test-skeleton.c" |