tests util/tfork: Tests for status and event fd
[nivanova/samba-autobuild/.git] / lib / util / tests / tfork.c
1 /*
2  * Tests for tfork
3  *
4  * Copyright Ralph Boehme <slow@samba.org> 2017
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "replace.h"
21 #include <talloc.h>
22 #include <tevent.h>
23 #include "system/filesys.h"
24 #include "system/wait.h"
25 #include "system/select.h"
26 #include "libcli/util/ntstatus.h"
27 #include "torture/torture.h"
28 #include "lib/util/data_blob.h"
29 #include "torture/local/proto.h"
30 #include "lib/util/tfork.h"
31 #include "lib/util/samba_util.h"
32 #include "lib/util/sys_rw.h"
33 #ifdef HAVE_PTHREAD
34 #include <pthread.h>
35 #include <sys/syscall.h>
36 #endif
37
38 static bool test_tfork_simple(struct torture_context *tctx)
39 {
40         pid_t parent = getpid();
41         struct tfork *t = NULL;
42         pid_t child;
43         int ret;
44
45         t = tfork_create();
46         if (t == NULL) {
47                 torture_fail(tctx, "tfork failed\n");
48                 return false;
49         }
50         child = tfork_child_pid(t);
51         if (child == 0) {
52                 torture_comment(tctx, "my parent pid is %d\n", parent);
53                 torture_assert(tctx, getpid() != parent, "tfork failed\n");
54                 _exit(0);
55         }
56
57         ret = tfork_destroy(&t);
58         torture_assert(tctx, ret == 0, "tfork_destroy failed\n");
59
60         return true;
61 }
62
63 static bool test_tfork_status(struct torture_context *tctx)
64 {
65         struct tfork *t = NULL;
66         int status;
67         pid_t child;
68         bool ok = true;
69
70         t = tfork_create();
71         if (t == NULL) {
72                 torture_fail(tctx, "tfork failed\n");
73                 return false;
74         }
75         child = tfork_child_pid(t);
76         if (child == 0) {
77                 _exit(123);
78         }
79
80         status = tfork_status(&t, true);
81         if (status == -1) {
82                 torture_fail(tctx, "tfork_status failed\n");
83         }
84
85         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
86                             "tfork failed\n");
87         torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done,
88                             "tfork failed\n");
89
90         torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status));
91
92 done:
93         return ok;
94 }
95
96 static bool test_tfork_sigign(struct torture_context *tctx)
97 {
98         struct tfork *t = NULL;
99         struct sigaction act;
100         pid_t child;
101         int status;
102         bool ok = true;
103         int ret;
104
105         act = (struct sigaction) {
106                 .sa_flags = SA_NOCLDWAIT,
107                 .sa_handler = SIG_IGN,
108         };
109
110         ret = sigaction(SIGCHLD, &act, NULL);
111         torture_assert_goto(tctx, ret == 0, ok, done, "sigaction failed\n");
112
113         t = tfork_create();
114         if (t == NULL) {
115                 torture_fail(tctx, "tfork failed\n");
116                 return false;
117         }
118         child = tfork_child_pid(t);
119         if (child == 0) {
120                 sleep(1);
121                 _exit(123);
122         }
123
124         child = fork();
125         if (child == -1) {
126                 torture_fail(tctx, "fork failed\n");
127                 return false;
128         }
129         if (child == 0) {
130                 _exit(0);
131         }
132
133         status = tfork_status(&t, true);
134         if (status == -1) {
135                 torture_fail(tctx, "tfork_status failed\n");
136         }
137
138         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
139                             "tfork failed\n");
140         torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done,
141                             "tfork failed\n");
142         torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status));
143
144 done:
145         return ok;
146 }
147
148 static void sigchld_handler1(int signum, siginfo_t *si, void *u)
149 {
150         pid_t pid;
151         int status;
152
153         if (signum != SIGCHLD) {
154                 abort();
155         }
156
157         pid = waitpid(si->si_pid, &status, 0);
158         if (pid != si->si_pid) {
159                 abort();
160         }
161 }
162
163 static bool test_tfork_sighandler(struct torture_context *tctx)
164 {
165         struct tfork *t = NULL;
166         struct sigaction act;
167         struct sigaction oldact;
168         pid_t child;
169         int status;
170         bool ok = true;
171         int ret;
172
173         act = (struct sigaction) {
174                 .sa_flags = SA_SIGINFO,
175                 .sa_sigaction = sigchld_handler1,
176         };
177
178         ret = sigaction(SIGCHLD, &act, &oldact);
179         torture_assert_goto(tctx, ret == 0, ok, done, "sigaction failed\n");
180
181         t = tfork_create();
182         if (t == NULL) {
183                 torture_fail(tctx, "tfork failed\n");
184                 return false;
185         }
186         child = tfork_child_pid(t);
187         if (child == 0) {
188                 sleep(1);
189                 _exit(123);
190         }
191
192         child = fork();
193         if (child == -1) {
194                 torture_fail(tctx, "fork failed\n");
195                 return false;
196         }
197         if (child == 0) {
198                 _exit(0);
199         }
200
201         status = tfork_status(&t, true);
202         if (status == -1) {
203                 torture_fail(tctx, "tfork_status failed\n");
204         }
205
206         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
207                             "tfork failed\n");
208         torture_assert_goto(tctx, WEXITSTATUS(status) == 123, ok, done,
209                             "tfork failed\n");
210         torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status));
211
212 done:
213         sigaction(SIGCHLD, &oldact, NULL);
214
215         return ok;
216 }
217
218 static bool test_tfork_process_hierarchy(struct torture_context *tctx)
219 {
220         struct tfork *t = NULL;
221         pid_t pid = getpid();
222         pid_t child;
223         pid_t pgid = getpgid(0);
224         pid_t sid = getsid(0);
225         char *procpath = NULL;
226         int status;
227         struct stat st;
228         int ret;
229         bool ok = true;
230
231         procpath = talloc_asprintf(tctx, "/proc/%d/status", getpid());
232         torture_assert_not_null(tctx, procpath, "talloc_asprintf failed\n");
233
234         ret = stat(procpath, &st);
235         TALLOC_FREE(procpath);
236         if (ret != 0) {
237                 if (errno == ENOENT) {
238                         torture_skip(tctx, "/proc missing\n");
239                 }
240                 torture_fail(tctx, "stat failed\n");
241         }
242
243         t = tfork_create();
244         if (t == NULL) {
245                 torture_fail(tctx, "tfork failed\n");
246                 return false;
247         }
248         child = tfork_child_pid(t);
249         if (child == 0) {
250                 char *cmd = NULL;
251                 FILE *fp = NULL;
252                 char line[64];
253                 char *p;
254                 pid_t ppid;
255
256                 torture_assert_goto(tctx, pgid == getpgid(0), ok, child_fail, "tfork failed\n");
257                 torture_assert_goto(tctx, sid == getsid(0), ok, child_fail, "tfork failed\n");
258
259                 cmd = talloc_asprintf(tctx, "cat /proc/%d/status | awk '/^PPid:/ {print $2}'", getppid());
260                 torture_assert_goto(tctx, cmd != NULL, ok, child_fail, "talloc_asprintf failed\n");
261
262                 fp = popen(cmd, "r");
263                 torture_assert_goto(tctx, fp != NULL, ok, child_fail, "popen failed\n");
264
265                 p = fgets(line, sizeof(line) - 1, fp);
266                 pclose(fp);
267                 torture_assert_goto(tctx, p != NULL, ok, child_fail, "popen failed\n");
268
269                 ret = sscanf(line, "%d", &ppid);
270                 torture_assert_goto(tctx, ret == 1, ok, child_fail, "sscanf failed\n");
271                 torture_assert_goto(tctx, ppid == pid, ok, child_fail, "process hierachy not rooted at caller\n");
272
273                 _exit(0);
274
275         child_fail:
276                 _exit(1);
277         }
278
279         status = tfork_status(&t, true);
280         if (status == -1) {
281                 torture_fail(tctx, "tfork_status failed\n");
282         }
283
284         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
285                             "tfork failed\n");
286         torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done,
287                             "tfork failed\n");
288         torture_comment(tctx, "exit status [%d]\n", WEXITSTATUS(status));
289
290 done:
291         return ok;
292 }
293
294 static bool test_tfork_pipe(struct torture_context *tctx)
295 {
296         struct tfork *t = NULL;
297         int status;
298         pid_t child;
299         int up[2];
300         int down[2];
301         char c;
302         int ret;
303         bool ok = true;
304
305         ret = pipe(&up[0]);
306         torture_assert(tctx, ret == 0, "pipe failed\n");
307
308         ret = pipe(&down[0]);
309         torture_assert(tctx, ret == 0, "pipe failed\n");
310
311         t = tfork_create();
312         if (t == NULL) {
313                 torture_fail(tctx, "tfork failed\n");
314                 return false;
315         }
316         child = tfork_child_pid(t);
317         if (child == 0) {
318                 close(up[0]);
319                 close(down[1]);
320
321                 ret = read(down[0], &c, 1);
322                 torture_assert_goto(tctx, ret == 1, ok, child_fail, "read failed\n");
323                 torture_assert_goto(tctx, c == 1, ok, child_fail, "read failed\n");
324
325                 ret = write(up[1], &(char){2}, 1);
326                 torture_assert_goto(tctx, ret == 1, ok, child_fail, "write failed\n");
327
328                 _exit(0);
329
330         child_fail:
331                 _exit(1);
332         }
333
334         close(up[1]);
335         close(down[0]);
336
337         ret = write(down[1], &(char){1}, 1);
338         torture_assert(tctx, ret == 1, "read failed\n");
339
340         ret = read(up[0], &c, 1);
341         torture_assert(tctx, ret == 1, "read failed\n");
342         torture_assert(tctx, c == 2, "read failed\n");
343
344         status = tfork_status(&t, true);
345         if (status == -1) {
346                 torture_fail(tctx, "tfork_status failed\n");
347         }
348
349         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
350                             "tfork failed\n");
351         torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done,
352                             "tfork failed\n");
353 done:
354         return ok;
355 }
356
357 static bool test_tfork_twice(struct torture_context *tctx)
358 {
359         struct tfork *t = NULL;
360         int status;
361         pid_t child;
362         pid_t pid;
363         int up[2];
364         int ret;
365         bool ok = true;
366
367         ret = pipe(&up[0]);
368         torture_assert(tctx, ret == 0, "pipe failed\n");
369
370         t = tfork_create();
371         if (t == NULL) {
372                 torture_fail(tctx, "tfork failed\n");
373                 return false;
374         }
375         child = tfork_child_pid(t);
376         if (child == 0) {
377                 close(up[0]);
378
379                 t = tfork_create();
380                 if (t == NULL) {
381                         torture_fail(tctx, "tfork failed\n");
382                         return false;
383                 }
384                 child = tfork_child_pid(t);
385                 if (child == 0) {
386                         sleep(1);
387                         pid = getpid();
388                         ret = write(up[1], &pid, sizeof(pid_t));
389                         torture_assert_goto(tctx, ret == sizeof(pid_t), ok, child_fail, "write failed\n");
390
391                         _exit(0);
392
393                 child_fail:
394                         _exit(1);
395                 }
396
397                 _exit(0);
398         }
399
400         close(up[1]);
401
402         ret = read(up[0], &pid, sizeof(pid_t));
403         torture_assert(tctx, ret == sizeof(pid_t), "read failed\n");
404
405         status = tfork_status(&t, true);
406         torture_assert_goto(tctx, status != -1, ok, done, "tfork_status failed\n");
407
408         torture_assert_goto(tctx, WIFEXITED(status) == true, ok, done,
409                             "tfork failed\n");
410         torture_assert_goto(tctx, WEXITSTATUS(status) == 0, ok, done,
411                             "tfork failed\n");
412 done:
413         return ok;
414 }
415
416 static void *tfork_thread(void *p)
417 {
418         struct tfork *t = NULL;
419         int status;
420         pid_t child;
421         pthread_t *ptid = (pthread_t *)p;
422         uint64_t tid;
423         uint64_t *result = NULL;
424         int up[2];
425         ssize_t nread;
426         int ret;
427
428         ret = pipe(up);
429         if (ret != 0) {
430                 pthread_exit(NULL);
431         }
432
433         tid = (uint64_t)*ptid;
434
435         t = tfork_create();
436         if (t == NULL) {
437                 pthread_exit(NULL);
438         }
439         child = tfork_child_pid(t);
440         if (child == 0) {
441                 ssize_t nwritten;
442
443                 close(up[0]);
444                 tid++;
445                 nwritten = sys_write(up[1], &tid, sizeof(uint64_t));
446                 if (nwritten != sizeof(uint64_t)) {
447                         _exit(1);
448                 }
449                 _exit(0);
450         }
451         close(up[1]);
452
453         result = malloc(sizeof(uint64_t));
454         if (result == NULL) {
455                 pthread_exit(NULL);
456         }
457
458         nread = sys_read(up[0], result, sizeof(uint64_t));
459         if (nread != sizeof(uint64_t)) {
460                 pthread_exit(NULL);
461         }
462
463         status = tfork_status(&t, true);
464         if (status == -1) {
465                 pthread_exit(NULL);
466         }
467
468         pthread_exit(result);
469 }
470
471 static bool test_tfork_threads(struct torture_context *tctx)
472 {
473         int ret;
474         bool ok = true;
475         const int num_threads = 64;
476         pthread_t threads[num_threads];
477         int i;
478
479 #ifndef HAVE_PTHREAD
480         torture_skip(tctx, "no pthread support\n");
481 #endif
482
483         for (i = 0; i < num_threads; i++) {
484                 ret = pthread_create(&threads[i], NULL, tfork_thread, &threads[i]);
485                 torture_assert_goto(tctx, ret == 0, ok, done,
486                                     "pthread_create failed\n");
487         }
488
489         for (i = 0; i < num_threads; i++) {
490                 void *p;
491                 uint64_t *result;
492
493                 ret = pthread_join(threads[i], &p);
494                 torture_assert_goto(tctx, ret == 0, ok, done,
495                                     "pthread_join failed\n");
496                 result = (uint64_t *)p;
497                 torture_assert_goto(tctx, *result == (uint64_t)threads[i] + 1,
498                                     ok, done, "thread failed\n");
499                 free(p);
500         }
501
502 done:
503         return ok;
504 }
505
506 static bool test_tfork_cmd_send(struct torture_context *tctx)
507 {
508         struct tevent_context *ev = NULL;
509         struct tevent_req *req = NULL;
510         const char *cmd[2] = { NULL, NULL };
511         bool ok = true;
512
513         ev = tevent_context_init(tctx);
514         torture_assert_goto(tctx, ev != NULL, ok, done,
515                             "tevent_context_init failed\n");
516
517         cmd[0] = talloc_asprintf(tctx, "%s/testprogs/blackbox/tfork.sh", SRCDIR);
518         torture_assert_goto(tctx, cmd[0] != NULL, ok, done,
519                             "talloc_asprintf failed\n");
520
521         req = samba_runcmd_send(tctx, ev, timeval_zero(), 0, 0,
522                                 cmd, "foo", NULL);
523         torture_assert_goto(tctx, req != NULL, ok, done,
524                             "samba_runcmd_send failed\n");
525
526         ok = tevent_req_poll(req, ev);
527         torture_assert_goto(tctx, ok, ok, done, "tevent_req_poll failed\n");
528
529         torture_comment(tctx, "samba_runcmd_send test finished\n");
530
531 done:
532         TALLOC_FREE(ev);
533
534         return ok;
535 }
536
537 /*
538  * Test to ensure that the event_fd becomes readable after
539  * a tfork_process terminates.
540  */
541 static bool test_tfork_event_file_handle(struct torture_context *tctx)
542 {
543         bool ok = true;
544
545         struct tfork *t1 = NULL;
546         pid_t child1;
547         struct pollfd poll1[] = { {-1, POLLIN} };
548
549         struct tfork *t2 = NULL;
550         pid_t child2;
551         struct pollfd poll2[] = { {-1, POLLIN} };
552
553
554         t1 = tfork_create();
555         if (t1 == NULL) {
556                 torture_fail(tctx, "tfork failed\n");
557                 return false;
558         }
559
560         child1 = tfork_child_pid(t1);
561         if (child1 == 0) {
562                 /*
563                  * Parent process will kill this with a SIGTERM
564                  * so 10 seconds should be plenty
565                  */
566                 sleep(10);
567                 exit(1);
568         }
569         poll1[0].fd = tfork_event_fd(t1);
570
571         t2 = tfork_create();
572         if (t2 == NULL) {
573                 torture_fail(tctx, "tfork failed\n");
574                 return false;
575         }
576         child2 = tfork_child_pid(t2);
577         if (child2 == 0) {
578                 /*
579                  * Parent process will kill this with a SIGTERM
580                  * so 10 seconds should be plenty
581                  */
582                 sleep(10);
583                 exit(2);
584         }
585         poll2[0].fd = tfork_event_fd(t2);
586
587         /*
588          * Have forked two process and are in the master process
589          * Expect that both event_fds are unreadable
590          */
591         poll(poll1, 1, 0);
592         ok = !(poll1[0].revents & POLLIN);
593         torture_assert_goto(tctx, ok, ok, done,
594                             "tfork process 1 event fd readable\n");
595         poll(poll2, 1, 0);
596         ok = !(poll2[0].revents & POLLIN);
597         torture_assert_goto(tctx, ok, ok, done,
598                             "tfork process 1 event fd readable\n");
599
600         /* Kill the first child process */
601         kill(child1, SIGKILL);
602         sleep(1);
603
604         /*
605          * Have killed the first child, so expect it's event_fd to have gone
606          * readable.
607          *
608          */
609         poll(poll1, 1, 0);
610         ok = (poll1[0].revents & POLLIN);
611         torture_assert_goto(tctx, ok, ok, done,
612                             "tfork process 1 event fd not readable\n");
613         poll(poll2, 1, 0);
614         ok = !(poll2[0].revents & POLLIN);
615         torture_assert_goto(tctx, ok, ok, done,
616                             "tfork process 2 event fd readable\n");
617
618         /* Kill the secind child process */
619         kill(child2, SIGKILL);
620         sleep(1);
621         /*
622          * Have killed the children, so expect their event_fd's to have gone
623          * readable.
624          *
625          */
626         poll(poll1, 1, 0);
627         ok = (poll1[0].revents & POLLIN);
628         torture_assert_goto(tctx, ok, ok, done,
629                             "tfork process 1 event fd not readable\n");
630         poll(poll2, 1, 0);
631         ok = (poll2[0].revents & POLLIN);
632         torture_assert_goto(tctx, ok, ok, done,
633                             "tfork process 2 event fd not readable\n");
634
635 done:
636         return ok;
637 }
638
639 /*
640  * Test to ensure that the status calls behave as expected after a process
641  * terminates.
642  *
643  * As the parent process owns the status fd's they get passed to all
644  * subsequent children after a tfork.  So it's possible for another
645  * child process to hold the status pipe open.
646  *
647  * The event fd needs to be left open by tfork, as a close in the status
648  * code can cause issues in tevent code.
649  *
650  */
651 static bool test_tfork_status_handle(struct torture_context *tctx)
652 {
653         bool ok = true;
654
655         struct tfork *t1 = NULL;
656         pid_t child1;
657
658         struct tfork *t2 = NULL;
659         pid_t child2;
660
661         int status;
662         int fd;
663         int ev1_fd;
664         int ev2_fd;
665
666
667         t1 = tfork_create();
668         if (t1 == NULL) {
669                 torture_fail(tctx, "tfork failed\n");
670                 return false;
671         }
672
673         child1 = tfork_child_pid(t1);
674         if (child1 == 0) {
675                 /*
676                  * Parent process will kill this with a SIGTERM
677                  * so 10 seconds should be plenty
678                  */
679                 sleep(10);
680                 exit(1);
681         }
682         ev1_fd = tfork_event_fd(t1);
683
684         t2 = tfork_create();
685         if (t2 == NULL) {
686                 torture_fail(tctx, "tfork failed\n");
687                 return false;
688         }
689         child2 = tfork_child_pid(t2);
690         if (child2 == 0) {
691                 /*
692                  * Parent process will kill this with a SIGTERM
693                  * so 10 seconds should be plenty
694                  */
695                 sleep(10);
696                 exit(2);
697         }
698         ev2_fd = tfork_event_fd(t2);
699
700         /*
701          * Have forked two process and are in the master process
702          * expect that the status call will block, and hence return -1
703          * as the processes are still running
704          * The event fd's should be open.
705          */
706         status = tfork_status(&t1, false);
707         ok = status == -1;
708         torture_assert_goto(tctx, ok, ok, done,
709                             "tfork status available for non terminated "
710                             "process 1\n");
711         /* Is the event fd open? */
712         fd = dup(ev1_fd);
713         ok = fd != -1;
714         torture_assert_goto(tctx, ok, ok, done,
715                             "tfork process 1 event fd is not open");
716
717         status = tfork_status(&t2, false);
718         ok = status == -1;
719         torture_assert_goto(tctx, ok, ok, done,
720                             "tfork status avaiable for non terminated "
721                             "process 2\n");
722         /* Is the event fd open? */
723         fd = dup(ev2_fd);
724         ok = fd != -1;
725         torture_assert_goto(tctx, ok, ok, done,
726                             "tfork process 2 event fd is not open");
727
728         /*
729          * Kill the first process, it's status should be readable
730          * and it's event_fd should be open
731          * The second process's status should be unreadable.
732          */
733         kill(child1, SIGTERM);
734         sleep(1);
735         status = tfork_status(&t1, false);
736         ok = status != -1;
737         torture_assert_goto(tctx, ok, ok, done,
738                             "tfork status for child 1 not available after "
739                             "termination\n");
740         /* Is the event fd open? */
741         fd = dup(ev2_fd);
742         ok = fd != -1;
743         torture_assert_goto(tctx, ok, ok, done,
744                             "tfork process 1 event fd is not open");
745
746         status = tfork_status(&t2, false);
747         ok = status == -1;
748         torture_assert_goto(tctx, ok, ok, done,
749                             "tfork status available for child 2 after "
750                             "termination of child 1\n");
751
752         /*
753          * Kill the second process, it's status should be readable
754          */
755         kill(child2, SIGTERM);
756         sleep(1);
757         status = tfork_status(&t2, false);
758         ok = status != -1;
759         torture_assert_goto(tctx, ok, ok, done,
760                             "tfork status for child 2 not available after "
761                             "termination\n");
762
763         /* Check that the event fd's are still open */
764         /* Is the event fd open? */
765         fd = dup(ev1_fd);
766         ok = fd != -1;
767         torture_assert_goto(tctx, ok, ok, done,
768                             "tfork process 1 event fd is not open");
769         /* Is the event fd open? */
770         fd = dup(ev2_fd);
771         ok = fd != -1;
772         torture_assert_goto(tctx, ok, ok, done,
773                             "tfork process 2 event fd is not open");
774
775 done:
776         return ok;
777 }
778
779 struct torture_suite *torture_local_tfork(TALLOC_CTX *mem_ctx)
780 {
781         struct torture_suite *suite =
782                 torture_suite_create(mem_ctx, "tfork");
783
784         torture_suite_add_simple_test(suite,
785                                       "tfork_simple",
786                                       test_tfork_simple);
787
788         torture_suite_add_simple_test(suite,
789                                       "tfork_status",
790                                       test_tfork_status);
791
792         torture_suite_add_simple_test(suite,
793                                       "tfork_sigign",
794                                       test_tfork_sigign);
795
796         torture_suite_add_simple_test(suite,
797                                       "tfork_sighandler",
798                                       test_tfork_sighandler);
799
800         torture_suite_add_simple_test(suite,
801                                       "tfork_process_hierarchy",
802                                       test_tfork_process_hierarchy);
803
804         torture_suite_add_simple_test(suite,
805                                       "tfork_pipe",
806                                       test_tfork_pipe);
807
808         torture_suite_add_simple_test(suite,
809                                       "tfork_twice",
810                                       test_tfork_twice);
811
812         torture_suite_add_simple_test(suite,
813                                       "tfork_threads",
814                                       test_tfork_threads);
815
816         torture_suite_add_simple_test(suite,
817                                       "tfork_cmd_send",
818                                       test_tfork_cmd_send);
819
820         torture_suite_add_simple_test(suite,
821                                       "tfork_event_file_handle",
822                                       test_tfork_event_file_handle);
823
824         torture_suite_add_simple_test(suite,
825                                       "tfork_status_handle",
826                                       test_tfork_status_handle);
827
828         return suite;
829 }