1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
33 /* $Id: sigrelse01.c,v 1.14 2009/08/28 14:10:16 vapier Exp $ */
34 /*****************************************************************************
35 * OS Test - Silicon Graphics, Inc. Eagan, Minnesota
36 *
37 * TEST IDENTIFIER : sigrelse01 Releasing held signals.
38 *
39 * PARENT DOCUMENT : sgrtds01 sigrelse system call
40 *
41 * AUTHOR : Bob Clark
42 * : Rewrote 12/92 by Richard Logan
43 *
44 * CO-PILOT : Dave Baumgartner
45 *
46 * DATE STARTED : 10/08/86
47 *
48 * TEST ITEMS
49 *
50 * 1. sigrelse turns on the receipt of signals held by sighold.
51 *
52 * SPECIAL PROCEDURAL REQUIRMENTS
53 * None
54 *
55 * DETAILED DESCRIPTION
56 * set up pipe for parent/child communications
57 * fork off a child process
58 *
59 * parent():
60 * set up for unexpected signals
61 * wait for child to send ready message over pipe
62 * send all catchable signals to child process
63 * send alarm signal to speed up timeout
64 * wait for child to terminate and check exit value
65 *
66 * if exit value is EXIT_OK
67 * get message from pipe (contains array of signal counters)
68 * loop through array of signal counters and record any
69 * signals which were not caught once.
70 * record PASS or FAIL depending on what was found in the array.
71 *
72 * else if exit is SIG_CAUGHT then BROK (signal caught
73 * before released)
74 * else if exit is WRITE_BROK then BROK (write() to pipe failed)
75 * else if exit is HANDLE_ERR then BROK (error in child's
76 * signal handler)
77 * else unexpected exit value - BROK
78 *
79 * child():
80 * phase 1:
81 * set up to catch all catchable signals (exit SIG_CAUGHT
82 * if caught)
83 * hold each signal with sighold()
84 * send parent ready message if setup went ok.
85 * wait for signals to arrive - timeout if they don't
86 *
87 * phase 2:
88 * release each signal and wait a second for the handler to
89 * catch it.
90 * (the handler will record each signal it catches in an array
91 * and exit HANDLE_ERR if an error occurs)
92 *
93 * send array of counters back to parent for processing.
94 * exit EXIT_OK
95 * NOTES
96 * since child is executing system calls under test, no
97 * system call times are printed.
98 *
99 ***************************************************************************/
100
101 #include <sys/types.h>
102 #include <sys/wait.h>
103 #include <errno.h>
104 #include <fcntl.h>
105 #include <signal.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #include <time.h>
109 #include <unistd.h>
110 #include "test.h"
111 #include "safe_macros.h"
112
113 #ifdef __linux__
114 /* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
115 extern int sighold(int __sig);
116 extern int sigrelse(int __sig);
117 #endif
118
119 /* Needed for NPTL */
120 #define SIGCANCEL 32
121 #define SIGTIMER 33
122
123 void setup(void);
124 void cleanup(void);
125 static void parent(void);
126 static void child(void);
127 static void timeout(int sig);
128 static int setup_sigs(void);
129 static void handler(int sig);
130 static void wait_a_while(void);
131 static char *read_pipe(int fd);
132 static int write_pipe(int fd, char *msg);
133 static int set_timeout(void);
134 static void clear_timeout(void);
135 static void getout(void);
136 int choose_sig(int sig);
137
138 #define TRUE 1
139 #define FALSE 0
140
141 #ifndef DEBUG
142 #define DEBUG 0
143 #endif
144
145 #define CHILD_EXIT(VAL) ((VAL >> 8) & 0377) /* exit value of child process */
146 #define CHILD_SIG(VAL) (VAL & 0377) /* signal value of child proc */
147
148 #define MAXMESG 512 /* the size of the message string */
149
150 #define READY "ready" /* signal to parent that child is set up */
151
152 #define TIMEOUT 30 /* time (sec) used in the alarm calls */
153
154 /* child exit values */
155 #define EXIT_OK 0
156 #define SIG_CAUGHT 8
157 #define WRITE_BROK 16
158 #define HANDLE_ERR 32
159
160 int TST_TOTAL = 1; /* number of test items */
161
162 char *TCID = "sigrelse01"; /* test case identifier */
163 static char mesg[MAXMESG]; /* message buffer for tst_res */
164 static int pid; /* process id of child */
165 static int pipe_fd[2]; /* file descriptors for pipe parent read */
166 static int pipe_fd2[2]; /* file descriptors for pipe child read */
167 static int phase; /* flag for phase1 or phase2 of */
168 /* signal handler */
169 static int sig_caught; /* flag TRUE if signal caught */
170 /* (see wait_a_while ()) */
171
172 /* ensure that NUMSIGS is defined. */
173 #ifndef NUMSIGS
174 #define NUMSIGS NSIG
175 #endif
176
177 /* array of counters for signals caught by handler() */
178 static int sig_array[NUMSIGS];
179
180 /***********************************************************************
181 * M A I N
182 ***********************************************************************/
main(int argc,char ** argv)183 int main(int argc, char **argv)
184 {
185 int lc;
186
187 /* gcc -Wall complains about sig_caught not being ref'd because of the
188 external declarations. */
189 sig_caught = FALSE;
190
191 /*
192 * parse standard options
193 */
194 tst_parse_opts(argc, argv, NULL, NULL);
195 #ifdef UCLINUX
196 maybe_run_child(&child, "dd", &pipe_fd[1], &pipe_fd2[0]);
197 #endif
198
199 /*
200 * perform global setup for test
201 */
202 setup();
203
204 for (lc = 0; TEST_LOOPING(lc); lc++) {
205
206 tst_count = 0;
207
208 /*
209 * fork off a child process
210 */
211 if ((pid = FORK_OR_VFORK()) < 0) {
212 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
213
214 } else if (pid > 0) {
215 parent();
216
217 } else {
218 #ifdef UCLINUX
219 if (self_exec(argv[0], "dd", pipe_fd[1], pipe_fd2[0]) <
220 0) {
221 tst_brkm(TBROK | TERRNO, cleanup,
222 "self_exec() failed");
223 }
224 #else
225 child();
226 #endif
227 }
228
229 }
230
231 cleanup();
232 tst_exit();
233
234 } /* end main */
235
236 /****************************************************************************
237 * parent() : wait for "ready" from child, send signals to child, wait for
238 * child to exit and report what happened.
239 ***************************************************************************/
parent(void)240 static void parent(void)
241 {
242 int term_stat; /* child return status */
243 int rv; /* function return value */
244 int sig; /* current signal number */
245 char *str; /* string returned from read_pipe() */
246 int *array; /* pointer to sig_array returned from child */
247 int fail = FALSE; /* flag indicating test item failure */
248 char big_mesg[MAXMESG * 6]; /* storage for big failure message */
249 int caught_sigs;
250
251 /* wait for "ready" message from child */
252 if ((str = read_pipe(pipe_fd[0])) == NULL) {
253 /* read_pipe() failed. */
254 tst_brkm(TBROK, getout, "%s", mesg);
255 }
256
257 if (strcmp(str, READY) != 0) {
258 /* child setup did not go well */
259 tst_brkm(TBROK, getout, "%s", str);
260 }
261
262 /*
263 * send signals to child and see if it holds them
264 */
265
266 for (sig = 1; sig < NUMSIGS; sig++) {
267 if (choose_sig(sig)) {
268 if (kill(pid, sig) < 0) {
269 if (errno == ESRCH) {
270 if (kill(pid, SIGTERM) < 0)
271 tst_brkm(TBROK | TERRNO, getout,
272 "kill(%d, %d) and kill(%d, SIGTERM) failed",
273 pid, sig, pid);
274 else
275 tst_brkm(TBROK | TERRNO, getout,
276 "kill(%d, %d) failed, but kill(%d, SIGTERM) worked",
277 pid, sig, pid);
278 } else
279 tst_brkm(TBROK | TERRNO, getout,
280 "kill(%d, %d) failed", pid,
281 sig);
282 }
283 }
284 }
285
286 if (write_pipe(pipe_fd2[1], READY) < 0) {
287 tst_brkm(TBROK | TERRNO, getout,
288 "Unable to tell child to go, write to pipe failed");
289 }
290
291 /*
292 * child is now releasing signals, wait and check exit value
293 */
294 SAFE_WAIT(getout, &term_stat);
295
296 /* check child's signal exit value */
297 if ((sig = CHILD_SIG(term_stat)) != 0)
298 /* the child was zapped by a signal */
299 tst_brkm(TBROK, cleanup, "Unexpected signal %d killed child",
300 sig);
301
302 /* get child exit value */
303
304 rv = CHILD_EXIT(term_stat);
305
306 switch (rv) {
307 case EXIT_OK:
308 /* sig_array sent back on pipe, check it out */
309 if ((array = (int *)read_pipe(pipe_fd[0])) == NULL) {
310 /* read_pipe() failed. */
311 tst_resm(TBROK, "%s", mesg);
312 break;
313 }
314 #if DEBUG > 1
315 for (sig = 1; sig < NUMSIGS; sig++) {
316 printf("array[%d] = %d\n", sig, array[sig]);
317 }
318 #endif
319 caught_sigs = 0;
320 for (sig = 1; sig < NUMSIGS; sig++) {
321 if (choose_sig(sig)) {
322 if (array[sig] != 1) {
323 /* sig was not caught or caught too many times */
324 (void)sprintf(mesg,
325 "\tsignal %d caught %d times (expected 1).\n",
326 sig, array[sig]);
327 (void)strcat(big_mesg, mesg);
328 fail = TRUE;
329 } else {
330 caught_sigs++;
331 }
332 }
333 } /* endfor */
334
335 if (fail == TRUE)
336 tst_resm(TFAIL, "%s", big_mesg);
337 else
338 tst_resm(TPASS,
339 "sigrelse() released all %d signals under test.",
340 caught_sigs);
341 break;
342
343 case TBROK:
344 /* get BROK message from pipe */
345 if ((str = read_pipe(pipe_fd[0])) == NULL) {
346 /* read_pipe() failed. */
347 tst_resm(TBROK, "%s", mesg);
348 break;
349 }
350
351 /* call tst_res: str contains the message */
352 tst_resm(TBROK, "%s", str);
353 break;
354 case SIG_CAUGHT:
355 /* a signal was caught before it was released */
356 tst_resm(TBROK, "A signal was caught before being released.");
357 break;
358 case WRITE_BROK:
359 /* the write() call failed in child's write_pipe */
360 tst_resm(TBROK, "write() pipe failed for child.");
361 break;
362 case HANDLE_ERR:
363 /* more than one signal tried to be handled at the same time */
364 tst_resm(TBROK, "Error occured in signal handler.");
365 break;
366 default:
367 tst_resm(TBROK, "Unexpected exit code %d from child", rv);
368 break;
369 }
370
371 } /* end of parent */
372
373 /****************************************************************************
374 * child() : hold signals, notify parent and wait for parent to send signals.
375 * If none were caught (sighold worked), release the signals one at a time
376 * and wait for them to be caught. Send results back to parent
377 * for processing.
378 ***************************************************************************/
child(void)379 static void child(void)
380 {
381 int rv; /* return value from sighold() and sigrelse() */
382 int sig; /* signal value */
383 int exit_val; /* exit value to send to parent */
384 char note[MAXMESG]; /* message buffer for pipe */
385 char *str;
386
387 phase = 1; /* tell handler that we do not want to catch signals */
388
389 /* set note to READY and if an error occurs, overwrite it */
390 (void)strcpy(note, READY);
391
392 /* set alarm in case something hangs */
393 if (set_timeout() < 0) {
394 /* an error occured - put mesg in note and send it back to parent */
395 (void)strcpy(note, mesg);
396
397 } else if (setup_sigs() < 0) {
398 /* an error occured - put mesg in note and send it back to parent */
399 (void)strcpy(note, mesg);
400
401 } else {
402 /* all set up to catch signals, now hold them */
403
404 for (sig = 1; sig < NUMSIGS; sig++) {
405 if (choose_sig(sig)) {
406 if ((rv = sighold(sig)) != 0) {
407 /* THEY say sighold ALWAYS returns 0 */
408 (void)sprintf(note,
409 "sighold did not return 0. rv:%d",
410 rv);
411 break;
412 }
413 }
414 }
415
416 }
417
418 /*
419 * send note to parent (if not READY, parent will BROK) and
420 * wait for parent to send signals. The timeout clock is set so
421 * that we will not wait forever - if sighold() did its job, we
422 * will not receive the signals. If sighold() blew it we will
423 * catch a signal and the interrupt handler will exit with a
424 * value of SIG_CAUGHT.
425 */
426 if (write_pipe(pipe_fd[1], note) < 0) {
427 /*
428 * write_pipe() failed. Set exit value to WRITE_BROK to let
429 * parent know what happened
430 */
431 clear_timeout();
432 exit(WRITE_BROK);
433 }
434
435 /*
436 * if we get to this point, all signals have been held and the
437 * timer has expired. Now what we want to do is release each
438 * signal and see if we catch it. If we catch all signals,
439 * sigrelse passed, else it failed.
440 */
441
442 phase = 2; /* let handler know we are now expecting signals */
443
444 #if DEBUG > 0
445 printf("child: PHASE II\n");
446 #endif
447
448 /* assume success and overwrite exit_val if an error occurs */
449 exit_val = EXIT_OK;
450
451 #if DEBUG > 0
452 printf("child: pid=%d waiting for parent's ready...\n", getpid());
453 #endif
454
455 /*
456 * wait for parent to tell us that sigals were all sent
457 */
458
459 /* wait for "ready" message from parent */
460 if ((str = read_pipe(pipe_fd2[0])) == NULL) {
461 /* read_pipe() failed. */
462 printf(" child: read_pipe failed\n");
463 exit(TBROK);
464 }
465
466 if (strcmp(str, READY) != 0) {
467 /* parent/pipe problem */
468 printf("child: didn't proper ready message\n");
469 exit(TBROK);
470 }
471
472 for (sig = 1; sig < NUMSIGS; sig++) {
473 if (choose_sig(sig)) {
474
475 /* all set up, release and catch a signal */
476
477 sig_caught = FALSE; /* handler sets it to TRUE when caught */
478 #if DEBUG > 1
479 printf("child: releasing sig %d...\n", sig);
480 #endif
481 if ((rv = sigrelse(sig)) != 0) {
482 /* THEY say sigrelse ALWAYS returns 0 */
483 (void)sprintf(note,
484 "sigrelse did not return 0. rv:%d",
485 rv);
486 exit_val = TBROK;
487 break;
488 }
489
490 /* give signal handler some time to process signal */
491 wait_a_while();
492 }
493
494 } /* endfor */
495
496 /*
497 * If we are error free so far...
498 * check the sig_array array for one occurence of
499 * each of the catchable signals. If this is true,
500 * then PASS, otherwise FAIL.
501 */
502
503 if (exit_val == EXIT_OK) {
504 (void)memcpy(note, (char *)sig_array,
505 sizeof(note) < sizeof(sig_array) ?
506 sizeof(note) : sizeof(sig_array));
507 }
508
509 /* send note to parent and exit */
510 if (write_pipe(pipe_fd[1], note) < 0) {
511 /*
512 * write_pipe() failed. Set exit value to WRITE_BROK to let
513 * parent know what happened
514 */
515 exit(WRITE_BROK);
516 }
517
518 exit(exit_val);
519
520 } /* end of child */
521
522 /*****************************************************************************
523 * setup_sigs() : set child up to catch all signals. If there is
524 * trouble, write message in mesg and return -1, else return 0.
525 * The signal handler has two functions depending on which phase
526 * of the test we are in. The first section is executed after the
527 * signals have been held (should not ever be used). The second
528 * section is executed after the signals have been released (should
529 * be executed for each signal).
530 ****************************************************************************/
setup_sigs(void)531 static int setup_sigs(void)
532 {
533 int sig;
534
535 /* set up signal handler routine */
536 for (sig = 1; sig < NUMSIGS; sig++) {
537 if (choose_sig(sig)) {
538 if (signal(sig, handler) == SIG_ERR) {
539 /* set up mesg to send back to parent */
540 (void)sprintf(mesg,
541 "signal() failed for signal %d. error:%d %s.",
542 sig, errno, strerror(errno));
543 return (-1);
544 }
545 }
546 }
547 return 0;
548
549 } /* end of setup_sigs */
550
551 /*****************************************************************************
552 * handler() : child's interrupt handler for all signals. The phase variable
553 * is set in the child process indicating what action is to be taken.
554 * The phase 1 section will be run if the child process catches a signal
555 * after the signal has been held resulting in a test item BROK.
556 * The parent detects this situation by a child exit value of SIG_CAUGHT.
557 * The phase 2 section will be run if the child process catches a
558 * signal after the signal has been released. All signals must be
559 * caught in order for a PASS.
560 ****************************************************************************/
handler(int sig)561 static void handler(int sig)
562 {
563 static int s = 0; /* semaphore so that we don't handle 2 */
564 /* sigs at once */
565 #if DEBUG > 1
566 printf("child: handler phase%d: caught signal %d.\n", phase, sig);
567 #endif
568
569 if (phase == 1) {
570 /* exit the child process with a value of -1 */
571 exit(SIG_CAUGHT);
572
573 } else {
574 /* phase 2 (error if s gets incremented twice) */
575 ++s;
576
577 if (s > 1) {
578 exit(HANDLE_ERR);
579 }
580
581 /* increment the array element for this signal */
582 ++sig_array[sig];
583 sig_caught = TRUE; /* flag for wait_a_while () */
584 --s;
585 }
586
587 return;
588
589 } /* end of handler */
590
591 /*****************************************************************************
592 * read_pipe() : read data from pipe and return in buf. If an error occurs
593 * put message in mesg and return NULL. Note: this routine sets a
594 * timeout signal in case the pipe is blocked.
595 ****************************************************************************/
read_pipe(int fd)596 static char *read_pipe(int fd)
597 {
598 static char buf[MAXMESG]; /* buffer for pipe read */
599 int ret;
600
601 #if DEBUG > 0
602 printf("read_pipe: pid=%d waiting...\n", getpid());
603 #endif
604
605 /* set timeout alarm in case the pipe is blocked */
606 if (set_timeout() < 0) {
607 /* an error occured, message in mesg */
608 return NULL;
609 }
610
611 ret = -1;
612 while (ret == -1) { /* while empty reads */
613 if ((ret = read(fd, buf, MAXMESG)) == 0) {
614 (void)sprintf(mesg, "read() pipe failed. error:%d %s.",
615 errno, strerror(errno));
616
617 clear_timeout();
618 return NULL;
619 }
620 }
621 clear_timeout();
622
623 #if DEBUG > 0
624 printf("read_pipe: pid=%d received: %s.\n", getpid(), buf);
625 #endif
626 return (buf);
627
628 } /* end of read_pipe */
629
630 /*****************************************************************************
631 * write_pipe(msg) : write msg to pipe. If it fails, put message in
632 * mesg and return -1, else return 0.
633 ****************************************************************************/
write_pipe(int fd,char * msg)634 static int write_pipe(int fd, char *msg)
635 {
636
637 #if DEBUG > 0
638 printf("write_pipe: pid=%d, sending %s.\n", getpid(), msg);
639 #endif
640
641 if (write(fd, msg, MAXMESG) < 0) {
642 (void)sprintf(mesg, "write() pipe failed. error:%d %s.",
643 errno, strerror(errno));
644
645 return (-1);
646 }
647 return 0;
648
649 } /* end of write_pipe */
650
651 /*****************************************************************************
652 * set_timeout() : set alarm to signal process after the period of time
653 * indicated by TIMEOUT. If the signal occurs, the routine timeout()
654 * will be executed. If all goes ok, return 0, else load message
655 * into mesg and return -1.
656 ****************************************************************************/
set_timeout(void)657 static int set_timeout(void)
658 {
659 if (signal(SIGALRM, timeout) == SIG_ERR) {
660 (void)sprintf(mesg,
661 "signal() failed for signal %d. error:%d %s.",
662 SIGALRM, errno, strerror(errno));
663 return (-1);
664 }
665
666 (void)alarm(TIMEOUT);
667 return 0;
668
669 } /* end of set_timeout */
670
671 /*****************************************************************************
672 * clear_timeout() : turn off the alarm so that SIGALRM will not get sent.
673 ****************************************************************************/
clear_timeout(void)674 static void clear_timeout(void)
675 {
676 (void)alarm(0);
677
678 } /* end of clear_timeout */
679
680 /*****************************************************************************
681 * timeout() : this routine is executed when the SIGALRM signal is
682 * caught. It does nothing but return - the read() on the pipe
683 * will fail.
684 ****************************************************************************/
timeout(int sig)685 static void timeout(int sig)
686 {
687 #if DEBUG > 0
688 printf("timeout: pid=%d sigalrm caught.\n", getpid());
689 #endif
690 }
691
692 /*****************************************************************************
693 * wait_a_while () : wait a while before returning.
694 ****************************************************************************/
wait_a_while(void)695 static void wait_a_while(void)
696 {
697 long btime;
698
699 btime = time(NULL);
700 while (time(NULL) - btime < TIMEOUT) {
701 if (sig_caught == TRUE)
702 break;
703 }
704 } /* end of wait_a_while */
705
getout(void)706 static void getout(void)
707 {
708 if (pid > 0 && kill(pid, SIGKILL) < 0)
709 tst_resm(TWARN, "kill(%d, SIGKILL) failed", pid);
710 cleanup();
711
712 } /* end of getout */
713
714 #ifdef VAX
sighold(int signo)715 static int sighold(int signo)
716 {
717 return 0;
718 }
719
sigrelse(signo)720 static int sigrelse(signo)
721 int signo;
722 {
723 return 0;
724 }
725 #endif
726
choose_sig(int sig)727 int choose_sig(int sig)
728 {
729 switch (sig) {
730
731 case SIGKILL:
732 case SIGSTOP:
733 case SIGTSTP:
734 case SIGCONT:
735 case SIGALRM:
736 case SIGCANCEL:
737 case SIGTIMER:
738 #ifdef SIGNOBDM
739 case SIGNOBDM:
740 #endif
741 #ifdef SIGTTIN
742 case SIGTTIN:
743 #endif
744 #ifdef SIGTTOU
745 case SIGTTOU:
746 #endif
747 #ifdef SIGPTINTR
748 case SIGPTINTR:
749 #endif
750 #ifdef SIGSWAP
751 case SIGSWAP:
752 #endif
753 return 0;
754
755 }
756
757 return 1;
758
759 }
760
setup(void)761 void setup(void)
762 {
763
764 tst_sig(FORK, DEF_HANDLER, cleanup);
765
766 TEST_PAUSE;
767
768 tst_tmpdir();
769
770 /* set up pipe for parent/child communications */
771 SAFE_PIPE(cleanup, pipe_fd);
772
773 /*
774 * Cause the read to return 0 once EOF is encountered and the
775 * read to return -1 if pipe is empty.
776 */
777 if (fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK) == -1)
778 tst_brkm(TBROK | TERRNO, cleanup,
779 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
780
781 /* set up pipe for parent/child communications */
782 SAFE_PIPE(cleanup, pipe_fd2);
783
784 /*
785 * Cause the read to return 0 once EOF is encountered and the
786 * read to return -1 if pipe is empty.
787 */
788 if (fcntl(pipe_fd2[0], F_SETFL, O_NONBLOCK) == -1)
789 tst_brkm(TBROK | TERRNO, cleanup,
790 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
791 }
792
cleanup(void)793 void cleanup(void)
794 {
795 tst_rmdir();
796
797 }
798