Sun Oct 31 22:05:35 2010 UTC ()
Since rump implicit threads now bind to proc1 instead of proc0, we
need our shovel threads bound to proc1 instead of proc0 in order
to have access to the same set of descriptors as the implicit thread
which opens the fd in the rump kernel.

Also, sprinkle some printfs and make failure more dramatic.

fixes the puffs tests.  pointed out by pgoyette.


(pooka)
diff -r1.3 -r1.4 src/tests/fs/common/fstest_puffs.c

cvs diff -r1.3 -r1.4 src/tests/fs/common/fstest_puffs.c (switch to unified diff)

--- src/tests/fs/common/fstest_puffs.c 2010/09/01 19:41:27 1.3
+++ src/tests/fs/common/fstest_puffs.c 2010/10/31 22:05:35 1.4
@@ -1,351 +1,361 @@ @@ -1,351 +1,361 @@
1/* $NetBSD: fstest_puffs.c,v 1.3 2010/09/01 19:41:27 pooka Exp $ */ 1/* $NetBSD: fstest_puffs.c,v 1.4 2010/10/31 22:05:35 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/mount.h> 29#include <sys/mount.h>
30#include <sys/socket.h> 30#include <sys/socket.h>
31#include <sys/statvfs.h> 31#include <sys/statvfs.h>
32#include <sys/wait.h> 32#include <sys/wait.h>
33 33
34#include <assert.h> 34#include <assert.h>
35#include <atf-c.h> 35#include <atf-c.h>
36#include <err.h> 36#include <err.h>
37#include <errno.h> 37#include <errno.h>
38#include <fcntl.h> 38#include <fcntl.h>
39#include <pthread.h> 39#include <pthread.h>
40#include <puffs.h> 40#include <puffs.h>
41#include <puffsdump.h> 41#include <puffsdump.h>
42#include <signal.h> 42#include <signal.h>
43#include <stdio.h> 43#include <stdio.h>
44#include <unistd.h> 44#include <unistd.h>
45#include <string.h> 45#include <string.h>
46#include <stdlib.h> 46#include <stdlib.h>
47 47
48#include <rump/rump.h> 48#include <rump/rump.h>
49#include <rump/rump_syscalls.h> 49#include <rump/rump_syscalls.h>
50 50
51#include "h_fsmacros.h" 51#include "h_fsmacros.h"
52 52
53#define BUFSIZE (128*1024) 53#define BUFSIZE (128*1024)
54#define DTFS_DUMP "-o","dump" 54#define DTFS_DUMP "-o","dump"
55 55
56/* 56/*
57 * Threads which shovel data between comfd and /dev/puffs. 57 * Threads which shovel data between comfd and /dev/puffs.
58 * (cannot use polling since fd's are in different namespaces) 58 * (cannot use polling since fd's are in different namespaces)
59 */ 59 */
60static void * 60static void *
61readshovel(void *arg) 61readshovel(void *arg)
62{ 62{
63 struct putter_hdr *phdr; 63 struct putter_hdr *phdr;
64 struct puffs_req *preq; 64 struct puffs_req *preq;
65 struct puffstestargs *args = arg; 65 struct puffstestargs *args = arg;
66 char buf[BUFSIZE]; 66 char buf[BUFSIZE];
67 int comfd, puffsfd; 67 int comfd, puffsfd;
68 68
69 comfd = args->pta_servfd; 69 comfd = args->pta_servfd;
70 puffsfd = args->pta_rumpfd; 70 puffsfd = args->pta_rumpfd;
71 71
72 phdr = (void *)buf; 72 phdr = (void *)buf;
73 preq = (void *)buf; 73 preq = (void *)buf;
74 74
75 rump_pub_lwproc_newlwp(0); 75 rump_pub_lwproc_newlwp(1);
76 76
77 for (;;) { 77 for (;;) {
78 ssize_t n; 78 ssize_t n;
79 79
80 n = rump_sys_read(puffsfd, buf, sizeof(*phdr)); 80 n = rump_sys_read(puffsfd, buf, sizeof(*phdr));
81 if (n <= 0) 81 if (n <= 0) {
 82 fprintf(stderr, "readshovel r1 %d / %d\n", n, errno);
82 break; 83 break;
 84 }
83 85
84 assert(phdr->pth_framelen < BUFSIZE); 86 assert(phdr->pth_framelen < BUFSIZE);
85 n = rump_sys_read(puffsfd, buf+sizeof(*phdr),  87 n = rump_sys_read(puffsfd, buf+sizeof(*phdr),
86 phdr->pth_framelen - sizeof(*phdr)); 88 phdr->pth_framelen - sizeof(*phdr));
87 if (n <= 0) 89 if (n <= 0) {
 90 fprintf(stderr, "readshovel r2 %d / %d\n", n, errno);
88 break; 91 break;
 92 }
89 93
90 /* Analyze request */ 94 /* Analyze request */
91 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { 95 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
92 assert(preq->preq_optype < PUFFS_VFS_MAX); 96 assert(preq->preq_optype < PUFFS_VFS_MAX);
93 args->pta_vfs_toserv_ops[preq->preq_optype]++; 97 args->pta_vfs_toserv_ops[preq->preq_optype]++;
94 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { 98 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
95 assert(preq->preq_optype < PUFFS_VN_MAX); 99 assert(preq->preq_optype < PUFFS_VN_MAX);
96 args->pta_vn_toserv_ops[preq->preq_optype]++; 100 args->pta_vn_toserv_ops[preq->preq_optype]++;
97 } 101 }
98 102
99 n = phdr->pth_framelen; 103 n = phdr->pth_framelen;
100 if (write(comfd, buf, n) != n) 104 if (write(comfd, buf, n) != n) {
 105 fprintf(stderr, "readshovel write %d / %d\n", n, errno);
101 break; 106 break;
 107 }
102 } 108 }
103 109
104 return NULL; 110 abort();
105} 111}
106 112
107static void * 113static void *
108writeshovel(void *arg) 114writeshovel(void *arg)
109{ 115{
110 struct puffstestargs *args = arg; 116 struct puffstestargs *args = arg;
111 struct putter_hdr *phdr; 117 struct putter_hdr *phdr;
112 char buf[BUFSIZE]; 118 char buf[BUFSIZE];
113 size_t toread; 119 size_t toread;
114 int comfd, puffsfd; 120 int comfd, puffsfd;
115 121
116 rump_pub_lwproc_newlwp(0); 122 rump_pub_lwproc_newlwp(1);
117 123
118 comfd = args->pta_servfd; 124 comfd = args->pta_servfd;
119 puffsfd = args->pta_rumpfd; 125 puffsfd = args->pta_rumpfd;
120 126
121 phdr = (struct putter_hdr *)buf; 127 phdr = (struct putter_hdr *)buf;
122 128
123 for (;;) { 129 for (;;) {
124 uint64_t off; 130 uint64_t off;
125 ssize_t n; 131 ssize_t n;
126 132
127 /* 133 /*
128 * Need to write everything to the "kernel" in one chunk, 134 * Need to write everything to the "kernel" in one chunk,
129 * so make sure we have it here. 135 * so make sure we have it here.
130 */ 136 */
131 off = 0; 137 off = 0;
132 toread = sizeof(struct putter_hdr); 138 toread = sizeof(struct putter_hdr);
133 assert(toread < BUFSIZE); 139 assert(toread < BUFSIZE);
134 do { 140 do {
135 n = read(comfd, buf+off, toread); 141 n = read(comfd, buf+off, toread);
136 if (n <= 0) { 142 if (n <= 0) {
 143 fprintf(stderr, "writeshovel read %d / %d\n",
 144 n, errno);
137 break; 145 break;
138 } 146 }
139 off += n; 147 off += n;
140 if (off >= sizeof(struct putter_hdr)) 148 if (off >= sizeof(struct putter_hdr))
141 toread = phdr->pth_framelen - off; 149 toread = phdr->pth_framelen - off;
142 else 150 else
143 toread = off - sizeof(struct putter_hdr); 151 toread = off - sizeof(struct putter_hdr);
144 } while (toread); 152 } while (toread);
145 153
146 n = rump_sys_write(puffsfd, buf, phdr->pth_framelen); 154 n = rump_sys_write(puffsfd, buf, phdr->pth_framelen);
147 if ((size_t)n != phdr->pth_framelen) 155 if ((size_t)n != phdr->pth_framelen) {
 156 fprintf(stderr, "writeshovel wr %d / %d\n", n, errno);
148 break; 157 break;
 158 }
149 } 159 }
150 160
151 return NULL; 161 abort();
152} 162}
153 163
154static void 164static void
155rumpshovels(struct puffstestargs *args) 165rumpshovels(struct puffstestargs *args)
156{ 166{
157 pthread_t pt; 167 pthread_t pt;
158 int rv; 168 int rv;
159 169
160 if ((rv = rump_init()) == -1) 170 if ((rv = rump_init()) == -1)
161 err(1, "rump_init"); 171 err(1, "rump_init");
162 172
163 if (pthread_create(&pt, NULL, readshovel, args) == -1) 173 if (pthread_create(&pt, NULL, readshovel, args) == -1)
164 err(1, "read shovel"); 174 err(1, "read shovel");
165 pthread_detach(pt); 175 pthread_detach(pt);
166 176
167 if (pthread_create(&pt, NULL, writeshovel, args) == -1) 177 if (pthread_create(&pt, NULL, writeshovel, args) == -1)
168 err(1, "write shovel"); 178 err(1, "write shovel");
169 pthread_detach(pt); 179 pthread_detach(pt);
170} 180}
171 181
172static void 182static void
173childfail(int sign) 183childfail(int sign)
174{ 184{
175 185
176 atf_tc_fail("child died"); /* almost signal-safe */ 186 atf_tc_fail("child died"); /* almost signal-safe */
177} 187}
178 188
179struct puffstestargs *theargs; /* XXX */ 189struct puffstestargs *theargs; /* XXX */
180 190
181/* XXX: we don't support size */ 191/* XXX: we don't support size */
182int 192int
183puffs_fstest_newfs(const atf_tc_t *tc, void **argp, 193puffs_fstest_newfs(const atf_tc_t *tc, void **argp,
184 const char *image, off_t size, void *fspriv) 194 const char *image, off_t size, void *fspriv)
185{ 195{
186 struct puffstestargs *args; 196 struct puffstestargs *args;
187 char dtfs_path[MAXPATHLEN]; 197 char dtfs_path[MAXPATHLEN];
188 char *dtfsargv[6]; 198 char *dtfsargv[6];
189 char **theargv; 199 char **theargv;
190 pid_t childpid; 200 pid_t childpid;
191 int *pflags; 201 int *pflags;
192 char comfd[16]; 202 char comfd[16];
193 int sv[2]; 203 int sv[2];
194 int mntflags; 204 int mntflags;
195 size_t len; 205 size_t len;
196 ssize_t n; 206 ssize_t n;
197 207
198 *argp = NULL; 208 *argp = NULL;
199 209
200 args = malloc(sizeof(*args)); 210 args = malloc(sizeof(*args));
201 if (args == NULL) 211 if (args == NULL)
202 return errno; 212 return errno;
203 213
204 pflags = &args->pta_pflags; 214 pflags = &args->pta_pflags;
205 215
206 /* build dtfs exec path from atf test dir */ 216 /* build dtfs exec path from atf test dir */
207 sprintf(dtfs_path, "%s/../puffs/h_dtfs/h_dtfs", 217 sprintf(dtfs_path, "%s/../puffs/h_dtfs/h_dtfs",
208 atf_tc_get_config_var(tc, "srcdir")); 218 atf_tc_get_config_var(tc, "srcdir"));
209 219
210 if (fspriv) { 220 if (fspriv) {
211 theargv = fspriv; 221 theargv = fspriv;
212 theargv[0] = dtfs_path; 222 theargv[0] = dtfs_path;
213 } else { 223 } else {
214 dtfsargv[0] = dtfs_path; 224 dtfsargv[0] = dtfs_path;
215 dtfsargv[1] = __UNCONST("-i"); 225 dtfsargv[1] = __UNCONST("-i");
216 dtfsargv[2] = __UNCONST("-s"); 226 dtfsargv[2] = __UNCONST("-s");
217 dtfsargv[3] = __UNCONST("dtfs"); 227 dtfsargv[3] = __UNCONST("dtfs");
218 dtfsargv[4] = __UNCONST("fictional"); 228 dtfsargv[4] = __UNCONST("fictional");
219 dtfsargv[5] = NULL; 229 dtfsargv[5] = NULL;
220 230
221 theargv = dtfsargv; 231 theargv = dtfsargv;
222 } 232 }
223 233
224 /* Create sucketpair for communication with the real file server */ 234 /* Create sucketpair for communication with the real file server */
225 if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1) 235 if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) == -1)
226 return errno; 236 return errno;
227 237
228 signal(SIGCHLD, childfail); 238 signal(SIGCHLD, childfail);
229 239
230 switch ((childpid = fork())) { 240 switch ((childpid = fork())) {
231 case 0: 241 case 0:
232 close(sv[1]); 242 close(sv[1]);
233 snprintf(comfd, sizeof(sv[0]), "%d", sv[0]); 243 snprintf(comfd, sizeof(sv[0]), "%d", sv[0]);
234 if (setenv("PUFFS_COMFD", comfd, 1) == -1) 244 if (setenv("PUFFS_COMFD", comfd, 1) == -1)
235 return errno; 245 return errno;
236 246
237 if (execvp(theargv[0], theargv) == -1) 247 if (execvp(theargv[0], theargv) == -1)
238 return errno; 248 return errno;
239 case -1: 249 case -1:
240 return errno; 250 return errno;
241 default: 251 default:
242 close(sv[0]); 252 close(sv[0]);
243 break; 253 break;
244 } 254 }
245 255
246 /* read args */ 256 /* read args */
247 if ((n = read(sv[1], &len, sizeof(len))) != sizeof(len)) 257 if ((n = read(sv[1], &len, sizeof(len))) != sizeof(len))
248 err(1, "mp 1 %zd", n); 258 err(1, "mp 1 %zd", n);
249 if (len > MAXPATHLEN) 259 if (len > MAXPATHLEN)
250 err(1, "mntpath > MAXPATHLEN"); 260 err(1, "mntpath > MAXPATHLEN");
251 if ((size_t)read(sv[1], args->pta_dir, len) != len) 261 if ((size_t)read(sv[1], args->pta_dir, len) != len)
252 err(1, "mp 2"); 262 err(1, "mp 2");
253 if (read(sv[1], &len, sizeof(len)) != sizeof(len)) 263 if (read(sv[1], &len, sizeof(len)) != sizeof(len))
254 err(1, "fn 1"); 264 err(1, "fn 1");
255 if (len > MAXPATHLEN) 265 if (len > MAXPATHLEN)
256 err(1, "devpath > MAXPATHLEN"); 266 err(1, "devpath > MAXPATHLEN");
257 if ((size_t)read(sv[1], args->pta_dev, len) != len) 267 if ((size_t)read(sv[1], args->pta_dev, len) != len)
258 err(1, "fn 2"); 268 err(1, "fn 2");
259 if (read(sv[1], &mntflags, sizeof(mntflags)) != sizeof(mntflags)) 269 if (read(sv[1], &mntflags, sizeof(mntflags)) != sizeof(mntflags))
260 err(1, "mntflags"); 270 err(1, "mntflags");
261 if (read(sv[1], &args->pta_pargslen, sizeof(args->pta_pargslen)) 271 if (read(sv[1], &args->pta_pargslen, sizeof(args->pta_pargslen))
262 != sizeof(args->pta_pargslen)) 272 != sizeof(args->pta_pargslen))
263 err(1, "puffstest_args len"); 273 err(1, "puffstest_args len");
264 args->pta_pargs = malloc(args->pta_pargslen); 274 args->pta_pargs = malloc(args->pta_pargslen);
265 if (args->pta_pargs == NULL) 275 if (args->pta_pargs == NULL)
266 err(1, "malloc"); 276 err(1, "malloc");
267 if (read(sv[1], args->pta_pargs, args->pta_pargslen) 277 if (read(sv[1], args->pta_pargs, args->pta_pargslen)
268 != (ssize_t)args->pta_pargslen) 278 != (ssize_t)args->pta_pargslen)
269 err(1, "puffstest_args"); 279 err(1, "puffstest_args");
270 if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags)) 280 if (read(sv[1], pflags, sizeof(*pflags)) != sizeof(*pflags))
271 err(1, "pflags"); 281 err(1, "pflags");
272 282
273 args->pta_childpid = childpid; 283 args->pta_childpid = childpid;
274 args->pta_servfd = sv[1]; 284 args->pta_servfd = sv[1];
275 strlcpy(args->pta_dev, image, sizeof(args->pta_dev)); 285 strlcpy(args->pta_dev, image, sizeof(args->pta_dev));
276 286
277 *argp = theargs = args; 287 *argp = theargs = args;
278 288
279 return 0; 289 return 0;
280} 290}
281 291
282int 292int
283puffs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags) 293puffs_fstest_mount(const atf_tc_t *tc, void *arg, const char *path, int flags)
284{ 294{
285 struct puffstestargs *pargs = arg; 295 struct puffstestargs *pargs = arg;
286 int fd; 296 int fd;
287 297
288 rump_init(); 298 rump_init();
289 fd = rump_sys_open("/dev/puffs", O_RDWR); 299 fd = rump_sys_open("/dev/puffs", O_RDWR);
290 if (fd == -1) 300 if (fd == -1)
291 return fd; 301 return fd;
292 302
293#if 0 303#if 0
294 pa->pa_fd = fd; 304 pa->pa_fd = fd;
295#else 305#else
296 assert(fd == 0); /* XXX: FIXME */ 306 assert(fd == 0); /* XXX: FIXME */
297#endif 307#endif
298 308
299 if (rump_sys_mkdir(path, 0777) == -1) 309 if (rump_sys_mkdir(path, 0777) == -1)
300 return -1; 310 return -1;
301 311
302 if (rump_sys_mount(MOUNT_PUFFS, path, flags, 312 if (rump_sys_mount(MOUNT_PUFFS, path, flags,
303 pargs->pta_pargs, pargs->pta_pargslen) == -1) { 313 pargs->pta_pargs, pargs->pta_pargslen) == -1) {
304 /* apply "to kill a child" to avoid atf hang (kludge) */ 314 /* apply "to kill a child" to avoid atf hang (kludge) */
305 kill(pargs->pta_childpid, SIGKILL); 315 kill(pargs->pta_childpid, SIGKILL);
306 return -1; 316 return -1;
307 } 317 }
308 318
309 pargs->pta_rumpfd = fd; 319 pargs->pta_rumpfd = fd;
310 rumpshovels(pargs); 320 rumpshovels(pargs);
311 321
312 return 0; 322 return 0;
313} 323}
314 324
315int 325int
316puffs_fstest_delfs(const atf_tc_t *tc, void *arg) 326puffs_fstest_delfs(const atf_tc_t *tc, void *arg)
317{ 327{
318 328
319 /* useless ... */ 329 /* useless ... */
320 return 0; 330 return 0;
321} 331}
322 332
323int 333int
324puffs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags) 334puffs_fstest_unmount(const atf_tc_t *tc, const char *path, int flags)
325{ 335{
326 struct puffstestargs *pargs = theargs; 336 struct puffstestargs *pargs = theargs;
327 int status; 337 int status;
328 int rv; 338 int rv;
329 339
330 /* ok, child might exit here */ 340 /* ok, child might exit here */
331 signal(SIGCHLD, SIG_IGN); 341 signal(SIGCHLD, SIG_IGN);
332 342
333 rv = rump_sys_unmount(path, flags); 343 rv = rump_sys_unmount(path, flags);
334 if (rv)  344 if (rv)
335 return rv; 345 return rv;
336 346
337 if ((rv = rump_sys_rmdir(path)) != 0) 347 if ((rv = rump_sys_rmdir(path)) != 0)
338 return rv; 348 return rv;
339 349
340 if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) 350 if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0)
341 return 0; 351 return 0;
342 kill(pargs->pta_childpid, SIGTERM); 352 kill(pargs->pta_childpid, SIGTERM);
343 usleep(10); 353 usleep(10);
344 if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0) 354 if (waitpid(pargs->pta_childpid, &status, WNOHANG) > 0)
345 return 0; 355 return 0;
346 kill(pargs->pta_childpid, SIGKILL); 356 kill(pargs->pta_childpid, SIGKILL);
347 usleep(500); 357 usleep(500);
348 wait(&status); 358 wait(&status);
349 359
350 return 0; 360 return 0;
351} 361}