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 if (wait(&term_stat) < 0)
295 tst_brkm(TBROK | TERRNO, getout, "wait() failed");
296
297 /* check child's signal exit value */
298 if ((sig = CHILD_SIG(term_stat)) != 0)
299 /* the child was zapped by a signal */
300 tst_brkm(TBROK, cleanup, "Unexpected signal %d killed child",
301 sig);
302
303 /* get child exit value */
304
305 rv = CHILD_EXIT(term_stat);
306
307 switch (rv) {
308 case EXIT_OK:
309 /* sig_array sent back on pipe, check it out */
310 if ((array = (int *)read_pipe(pipe_fd[0])) == NULL) {
311 /* read_pipe() failed. */
312 tst_resm(TBROK, "%s", mesg);
313 break;
314 }
315 #if DEBUG > 1
316 for (sig = 1; sig < NUMSIGS; sig++) {
317 printf("array[%d] = %d\n", sig, array[sig]);
318 }
319 #endif
320 caught_sigs = 0;
321 for (sig = 1; sig < NUMSIGS; sig++) {
322 if (choose_sig(sig)) {
323 if (array[sig] != 1) {
324 /* sig was not caught or caught too many times */
325 (void)sprintf(mesg,
326 "\tsignal %d caught %d times (expected 1).\n",
327 sig, array[sig]);
328 (void)strcat(big_mesg, mesg);
329 fail = TRUE;
330 } else {
331 caught_sigs++;
332 }
333 }
334 } /* endfor */
335
336 if (fail == TRUE)
337 tst_resm(TFAIL, "%s", big_mesg);
338 else
339 tst_resm(TPASS,
340 "sigrelse() released all %d signals under test.",
341 caught_sigs);
342 break;
343
344 case TBROK:
345 /* get BROK message from pipe */
346 if ((str = read_pipe(pipe_fd[0])) == NULL) {
347 /* read_pipe() failed. */
348 tst_resm(TBROK, "%s", mesg);
349 break;
350 }
351
352 /* call tst_res: str contains the message */
353 tst_resm(TBROK, "%s", str);
354 break;
355 case SIG_CAUGHT:
356 /* a signal was caught before it was released */
357 tst_resm(TBROK, "A signal was caught before being released.");
358 break;
359 case WRITE_BROK:
360 /* the write() call failed in child's write_pipe */
361 tst_resm(TBROK, "write() pipe failed for child.");
362 break;
363 case HANDLE_ERR:
364 /* more than one signal tried to be handled at the same time */
365 tst_resm(TBROK, "Error occured in signal handler.");
366 break;
367 default:
368 tst_resm(TBROK, "Unexpected exit code %d from child", rv);
369 break;
370 }
371
372 } /* end of parent */
373
374 /****************************************************************************
375 * child() : hold signals, notify parent and wait for parent to send signals.
376 * If none were caught (sighold worked), release the signals one at a time
377 * and wait for them to be caught. Send results back to parent
378 * for processing.
379 ***************************************************************************/
child(void)380 static void child(void)
381 {
382 int rv; /* return value from sighold() and sigrelse() */
383 int sig; /* signal value */
384 int exit_val; /* exit value to send to parent */
385 char note[MAXMESG]; /* message buffer for pipe */
386 char *str;
387
388 phase = 1; /* tell handler that we do not want to catch signals */
389
390 /* set note to READY and if an error occurs, overwrite it */
391 (void)strcpy(note, READY);
392
393 /* set alarm in case something hangs */
394 if (set_timeout() < 0) {
395 /* an error occured - put mesg in note and send it back to parent */
396 (void)strcpy(note, mesg);
397
398 } else if (setup_sigs() < 0) {
399 /* an error occured - put mesg in note and send it back to parent */
400 (void)strcpy(note, mesg);
401
402 } else {
403 /* all set up to catch signals, now hold them */
404
405 for (sig = 1; sig < NUMSIGS; sig++) {
406 if (choose_sig(sig)) {
407 if ((rv = sighold(sig)) != 0) {
408 /* THEY say sighold ALWAYS returns 0 */
409 (void)sprintf(note,
410 "sighold did not return 0. rv:%d",
411 rv);
412 break;
413 }
414 }
415 }
416
417 }
418
419 /*
420 * send note to parent (if not READY, parent will BROK) and
421 * wait for parent to send signals. The timeout clock is set so
422 * that we will not wait forever - if sighold() did its job, we
423 * will not receive the signals. If sighold() blew it we will
424 * catch a signal and the interrupt handler will exit with a
425 * value of SIG_CAUGHT.
426 */
427 if (write_pipe(pipe_fd[1], note) < 0) {
428 /*
429 * write_pipe() failed. Set exit value to WRITE_BROK to let
430 * parent know what happened
431 */
432 clear_timeout();
433 exit(WRITE_BROK);
434 }
435
436 /*
437 * if we get to this point, all signals have been held and the
438 * timer has expired. Now what we want to do is release each
439 * signal and see if we catch it. If we catch all signals,
440 * sigrelse passed, else it failed.
441 */
442
443 phase = 2; /* let handler know we are now expecting signals */
444
445 #if DEBUG > 0
446 printf("child: PHASE II\n");
447 #endif
448
449 /* assume success and overwrite exit_val if an error occurs */
450 exit_val = EXIT_OK;
451
452 #if DEBUG > 0
453 printf("child: pid=%d waiting for parent's ready...\n", getpid());
454 #endif
455
456 /*
457 * wait for parent to tell us that sigals were all sent
458 */
459
460 /* wait for "ready" message from parent */
461 if ((str = read_pipe(pipe_fd2[0])) == NULL) {
462 /* read_pipe() failed. */
463 printf(" child: read_pipe failed\n");
464 exit(TBROK);
465 }
466
467 if (strcmp(str, READY) != 0) {
468 /* parent/pipe problem */
469 printf("child: didn't proper ready message\n");
470 exit(TBROK);
471 }
472
473 for (sig = 1; sig < NUMSIGS; sig++) {
474 if (choose_sig(sig)) {
475
476 /* all set up, release and catch a signal */
477
478 sig_caught = FALSE; /* handler sets it to TRUE when caught */
479 #if DEBUG > 1
480 printf("child: releasing sig %d...\n", sig);
481 #endif
482 if ((rv = sigrelse(sig)) != 0) {
483 /* THEY say sigrelse ALWAYS returns 0 */
484 (void)sprintf(note,
485 "sigrelse did not return 0. rv:%d",
486 rv);
487 exit_val = TBROK;
488 break;
489 }
490
491 /* give signal handler some time to process signal */
492 wait_a_while();
493 }
494
495 } /* endfor */
496
497 /*
498 * If we are error free so far...
499 * check the sig_array array for one occurence of
500 * each of the catchable signals. If this is true,
501 * then PASS, otherwise FAIL.
502 */
503
504 if (exit_val == EXIT_OK) {
505 (void)memcpy(note, (char *)sig_array,
506 sizeof(note) < sizeof(sig_array) ?
507 sizeof(note) : sizeof(sig_array));
508 }
509
510 /* send note to parent and exit */
511 if (write_pipe(pipe_fd[1], note) < 0) {
512 /*
513 * write_pipe() failed. Set exit value to WRITE_BROK to let
514 * parent know what happened
515 */
516 exit(WRITE_BROK);
517 }
518
519 exit(exit_val);
520
521 } /* end of child */
522
523 /*****************************************************************************
524 * setup_sigs() : set child up to catch all signals. If there is
525 * trouble, write message in mesg and return -1, else return 0.
526 * The signal handler has two functions depending on which phase
527 * of the test we are in. The first section is executed after the
528 * signals have been held (should not ever be used). The second
529 * section is executed after the signals have been released (should
530 * be executed for each signal).
531 ****************************************************************************/
setup_sigs(void)532 static int setup_sigs(void)
533 {
534 int sig;
535
536 /* set up signal handler routine */
537 for (sig = 1; sig < NUMSIGS; sig++) {
538 if (choose_sig(sig)) {
539 if (signal(sig, handler) == SIG_ERR) {
540 /* set up mesg to send back to parent */
541 (void)sprintf(mesg,
542 "signal() failed for signal %d. error:%d %s.",
543 sig, errno, strerror(errno));
544 return (-1);
545 }
546 }
547 }
548 return 0;
549
550 } /* end of setup_sigs */
551
552 /*****************************************************************************
553 * handler() : child's interrupt handler for all signals. The phase variable
554 * is set in the child process indicating what action is to be taken.
555 * The phase 1 section will be run if the child process catches a signal
556 * after the signal has been held resulting in a test item BROK.
557 * The parent detects this situation by a child exit value of SIG_CAUGHT.
558 * The phase 2 section will be run if the child process catches a
559 * signal after the signal has been released. All signals must be
560 * caught in order for a PASS.
561 ****************************************************************************/
handler(int sig)562 static void handler(int sig)
563 {
564 static int s = 0; /* semaphore so that we don't handle 2 */
565 /* sigs at once */
566 #if DEBUG > 1
567 printf("child: handler phase%d: caught signal %d.\n", phase, sig);
568 #endif
569
570 if (phase == 1) {
571 /* exit the child process with a value of -1 */
572 exit(SIG_CAUGHT);
573
574 } else {
575 /* phase 2 (error if s gets incremented twice) */
576 ++s;
577
578 if (s > 1) {
579 exit(HANDLE_ERR);
580 }
581
582 /* increment the array element for this signal */
583 ++sig_array[sig];
584 sig_caught = TRUE; /* flag for wait_a_while () */
585 --s;
586 }
587
588 return;
589
590 } /* end of handler */
591
592 /*****************************************************************************
593 * read_pipe() : read data from pipe and return in buf. If an error occurs
594 * put message in mesg and return NULL. Note: this routine sets a
595 * timeout signal in case the pipe is blocked.
596 ****************************************************************************/
read_pipe(int fd)597 static char *read_pipe(int fd)
598 {
599 static char buf[MAXMESG]; /* buffer for pipe read */
600 int ret;
601
602 #if DEBUG > 0
603 printf("read_pipe: pid=%d waiting...\n", getpid());
604 #endif
605
606 /* set timeout alarm in case the pipe is blocked */
607 if (set_timeout() < 0) {
608 /* an error occured, message in mesg */
609 return NULL;
610 }
611
612 ret = -1;
613 while (ret == -1) { /* while empty reads */
614 if ((ret = read(fd, buf, MAXMESG)) == 0) {
615 (void)sprintf(mesg, "read() pipe failed. error:%d %s.",
616 errno, strerror(errno));
617
618 clear_timeout();
619 return NULL;
620 }
621 }
622 clear_timeout();
623
624 #if DEBUG > 0
625 printf("read_pipe: pid=%d received: %s.\n", getpid(), buf);
626 #endif
627 return (buf);
628
629 } /* end of read_pipe */
630
631 /*****************************************************************************
632 * write_pipe(msg) : write msg to pipe. If it fails, put message in
633 * mesg and return -1, else return 0.
634 ****************************************************************************/
write_pipe(int fd,char * msg)635 static int write_pipe(int fd, char *msg)
636 {
637
638 #if DEBUG > 0
639 printf("write_pipe: pid=%d, sending %s.\n", getpid(), msg);
640 #endif
641
642 if (write(fd, msg, MAXMESG) < 0) {
643 (void)sprintf(mesg, "write() pipe failed. error:%d %s.",
644 errno, strerror(errno));
645
646 return (-1);
647 }
648 return 0;
649
650 } /* end of write_pipe */
651
652 /*****************************************************************************
653 * set_timeout() : set alarm to signal process after the period of time
654 * indicated by TIMEOUT. If the signal occurs, the routine timeout()
655 * will be executed. If all goes ok, return 0, else load message
656 * into mesg and return -1.
657 ****************************************************************************/
set_timeout(void)658 static int set_timeout(void)
659 {
660 if (signal(SIGALRM, timeout) == SIG_ERR) {
661 (void)sprintf(mesg,
662 "signal() failed for signal %d. error:%d %s.",
663 SIGALRM, errno, strerror(errno));
664 return (-1);
665 }
666
667 (void)alarm(TIMEOUT);
668 return 0;
669
670 } /* end of set_timeout */
671
672 /*****************************************************************************
673 * clear_timeout() : turn off the alarm so that SIGALRM will not get sent.
674 ****************************************************************************/
clear_timeout(void)675 static void clear_timeout(void)
676 {
677 (void)alarm(0);
678
679 } /* end of clear_timeout */
680
681 /*****************************************************************************
682 * timeout() : this routine is executed when the SIGALRM signal is
683 * caught. It does nothing but return - the read() on the pipe
684 * will fail.
685 ****************************************************************************/
timeout(int sig)686 static void timeout(int sig)
687 {
688 #if DEBUG > 0
689 printf("timeout: pid=%d sigalrm caught.\n", getpid());
690 #endif
691 }
692
693 /*****************************************************************************
694 * wait_a_while () : wait a while before returning.
695 ****************************************************************************/
wait_a_while(void)696 static void wait_a_while(void)
697 {
698 long btime;
699
700 btime = time(NULL);
701 while (time(NULL) - btime < TIMEOUT) {
702 if (sig_caught == TRUE)
703 break;
704 }
705 } /* end of wait_a_while */
706
getout(void)707 static void getout(void)
708 {
709 if (pid > 0 && kill(pid, SIGKILL) < 0)
710 tst_resm(TWARN, "kill(%d, SIGKILL) failed", pid);
711 cleanup();
712
713 } /* end of getout */
714
715 #ifdef VAX
sighold(int signo)716 static int sighold(int signo)
717 {
718 return 0;
719 }
720
sigrelse(signo)721 static int sigrelse(signo)
722 int signo;
723 {
724 return 0;
725 }
726 #endif
727
choose_sig(int sig)728 int choose_sig(int sig)
729 {
730 switch (sig) {
731
732 case SIGKILL:
733 case SIGSTOP:
734 case SIGTSTP:
735 case SIGCONT:
736 case SIGALRM:
737 case SIGCANCEL:
738 case SIGTIMER:
739 #ifdef SIGNOBDM
740 case SIGNOBDM:
741 #endif
742 #ifdef SIGTTIN
743 case SIGTTIN:
744 #endif
745 #ifdef SIGTTOU
746 case SIGTTOU:
747 #endif
748 #ifdef SIGPTINTR
749 case SIGPTINTR:
750 #endif
751 #ifdef SIGSWAP
752 case SIGSWAP:
753 #endif
754 return 0;
755
756 }
757
758 return 1;
759
760 }
761
setup(void)762 void setup(void)
763 {
764
765 tst_sig(FORK, DEF_HANDLER, cleanup);
766
767 TEST_PAUSE;
768
769 tst_tmpdir();
770
771 /* set up pipe for parent/child communications */
772 SAFE_PIPE(cleanup, pipe_fd);
773
774 /*
775 * Cause the read to return 0 once EOF is encountered and the
776 * read to return -1 if pipe is empty.
777 */
778 if (fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK) == -1)
779 tst_brkm(TBROK | TERRNO, cleanup,
780 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
781
782 /* set up pipe for parent/child communications */
783 SAFE_PIPE(cleanup, pipe_fd2);
784
785 /*
786 * Cause the read to return 0 once EOF is encountered and the
787 * read to return -1 if pipe is empty.
788 */
789 if (fcntl(pipe_fd2[0], F_SETFL, O_NONBLOCK) == -1)
790 tst_brkm(TBROK | TERRNO, cleanup,
791 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
792 }
793
cleanup(void)794 void cleanup(void)
795 {
796 tst_rmdir();
797
798 }
799