diff options
author | Egor Duda <deo@logos-m.ru> | 2001-09-13 17:30:23 +0000 |
---|---|---|
committer | Egor Duda <deo@logos-m.ru> | 2001-09-13 17:30:23 +0000 |
commit | 50ab44e0a7799fa79e4fc1c140f95a0aca2cda33 (patch) | |
tree | 453ab71966e21eced69768abb97a106993a13a30 /winsup/testsuite/winsup.api/ltp/kill02.c | |
parent | 4e8b5fc38766dc653bc503bb9d2cc56fc69240c4 (diff) | |
download | cygnal-50ab44e0a7799fa79e4fc1c140f95a0aca2cda33.tar.gz cygnal-50ab44e0a7799fa79e4fc1c140f95a0aca2cda33.tar.bz2 cygnal-50ab44e0a7799fa79e4fc1c140f95a0aca2cda33.zip |
* libltp/lib/tst_sig.c: Pass SIGSEGV to application to consider
whether it's expected or not.
* winsup.api/known_bugs.tcl: lseek10 is known to fail because mknod
is not implemented.
* winsup.api/ltp/rename02.c: Fix formatting.
* libltp/lib/libtestsuite.c: New file.
* winsup.api/signal-into-win32-api.c: New test.
* winsup.api/ltp/access04.c: Ditto.
* winsup.api/ltp/access05.c: Ditto.
* winsup.api/ltp/alarm07.c: Ditto.
* winsup.api/ltp/chdir04.c: Ditto.
* winsup.api/ltp/chmod01.c: Ditto.
* winsup.api/ltp/close01.c: Ditto.
* winsup.api/ltp/close02.c: Ditto.
* winsup.api/ltp/creat01.c: Ditto.
* winsup.api/ltp/creat03.c: Ditto.
* winsup.api/ltp/exit01.c: Ditto.
* winsup.api/ltp/exit02.c: Ditto.
* winsup.api/ltp/fchdir01.c: Ditto.
* winsup.api/ltp/fchdir02.c: Ditto.
* winsup.api/ltp/fork02.c: Ditto.
* winsup.api/ltp/fork03.c: Ditto.
* winsup.api/ltp/fork06.c: Ditto.
* winsup.api/ltp/fork07.c: Ditto.
* winsup.api/ltp/fork09.c: Ditto.
* winsup.api/ltp/fork10.c: Ditto.
* winsup.api/ltp/fork11.c: Ditto.
* winsup.api/ltp/fstat02.c: Ditto.
* winsup.api/ltp/fstat03.c: Ditto.
* winsup.api/ltp/fstat04.c: Ditto.
* winsup.api/ltp/ftruncate01.c: Ditto.
* winsup.api/ltp/ftruncate02.c: Ditto.
* winsup.api/ltp/ftruncate03.c: Ditto.
* winsup.api/ltp/getgid02.c: Ditto.
* winsup.api/ltp/getgid03.c: Ditto.
* winsup.api/ltp/getpgid01.c: Ditto.
* winsup.api/ltp/getpgid02.c: Ditto.
* winsup.api/ltp/getpid02.c: Ditto.
* winsup.api/ltp/getppid02.c: Ditto.
* winsup.api/ltp/getuid02.c: Ditto.
* winsup.api/ltp/getuid03.c: Ditto.
* winsup.api/ltp/kill01.c: Ditto.
* winsup.api/ltp/kill02.c: Ditto.
* winsup.api/ltp/kill03.c: Ditto.
* winsup.api/ltp/kill04.c: Ditto.
* winsup.api/ltp/lseek06.c: Ditto.
* winsup.api/ltp/lseek07.c: Ditto.
* winsup.api/ltp/lseek08.c: Ditto.
* winsup.api/ltp/lseek09.c: Ditto.
* winsup.api/ltp/lseek10.c: Ditto.
* winsup.api/ltp/mmap02.c: Ditto.
* winsup.api/ltp/mmap03.c: Ditto.
* winsup.api/ltp/mmap04.c: Ditto.
* winsup.api/ltp/mmap05.c: Ditto.
* winsup.api/ltp/mmap06.c: Ditto.
* winsup.api/ltp/mmap07.c: Ditto.
* winsup.api/ltp/mmap08.c: Ditto.
* winsup.api/ltp/munmap01.c: Ditto.
* winsup.api/ltp/munmap02.c: Ditto.
* winsup.api/ltp/open02.c: Ditto.
* winsup.api/ltp/pipe01.c: Ditto.
* winsup.api/ltp/pipe08.c: Ditto.
* winsup.api/ltp/pipe09.c: Ditto.
* winsup.api/ltp/pipe10.c: Ditto.
* winsup.api/ltp/pipe11.c: Ditto.
* winsup.api/ltp/poll01.c: Ditto.
* winsup.api/ltp/read04.c: Ditto.
* winsup.api/ltp/readlink01.c: Ditto.
* winsup.api/ltp/readlink03.c: Ditto.
* winsup.api/ltp/rename01.c: Ditto.
* winsup.api/ltp/rename08.c: Ditto.
* winsup.api/ltp/rename10.c: Ditto.
* winsup.api/ltp/rmdir01.c: Ditto.
* winsup.api/ltp/stat01.c: Ditto.
* winsup.api/ltp/stat02.c: Ditto.
* winsup.api/ltp/stat03.c: Ditto.
* winsup.api/ltp/symlink03.c: Ditto.
* winsup.api/ltp/symlink04.c: Ditto.
* winsup.api/ltp/symlink05.c: Ditto.
* winsup.api/ltp/sync02.c: Ditto.
* winsup.api/ltp/time02.c: Ditto.
* winsup.api/ltp/times02.c: Ditto.
* winsup.api/ltp/times03.c: Ditto.
* winsup.api/ltp/truncate01.c: Ditto.
* winsup.api/ltp/truncate02.c: Ditto.
* winsup.api/ltp/umask02.c: Ditto.
* winsup.api/ltp/umask03.c: Ditto.
* winsup.api/ltp/wait401.c: Ditto.
* winsup.api/ltp/wait402.c: Ditto.
* winsup.api/ltp/write02.c: Ditto.
* winsup.api/ltp/write03.c: Ditto.
Diffstat (limited to 'winsup/testsuite/winsup.api/ltp/kill02.c')
-rw-r--r-- | winsup/testsuite/winsup.api/ltp/kill02.c | 858 |
1 files changed, 858 insertions, 0 deletions
diff --git a/winsup/testsuite/winsup.api/ltp/kill02.c b/winsup/testsuite/winsup.api/ltp/kill02.c new file mode 100644 index 000000000..e618c8c71 --- /dev/null +++ b/winsup/testsuite/winsup.api/ltp/kill02.c @@ -0,0 +1,858 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ + * + */ +/* $Id$ */ +/*********************************************************************************** + + OS Test - Silicon Graphics, Inc. + + TEST IDENTIFIER : kill02 Sending a signal to processes with the same process group ID. + + PARENT DOCUMENT : kiltds01 Kill System Call. + + AUTHOR : Dave Baumgartner + + CO-PILOT : Barrie Kletscher + + DATE STARTED : 12/30/85 + + TEST ITEMS + + 1. Sending a signal to pid of zero sends to all processes whose process + group ID is equal to the process group ID as the sender. + + 2. Sending a signal to pid of zero does not send to processes in another process group. + + + OUTPUT SPECIFICATIONS + + PASS : + kiltcs02 1 PASS The signal was sent to all processes in the process group. + kiltcs02 2 PASS The signal was not sent to selective processes that were not in the process group. + + FAIL : + kiltcs02 1 FAIL The signal was not sent to all processes in the process group. + kiltcs02 2 FAIL The signal was sent to a process that was not in the process group. + + BROK : + kiltcs02 # BROK System call XXX failed. Errno:X, Error message:XXX. + kiltcs02 # BROK Setting to catch unexpected signal %d failed. Errno: %d, Error message %s. + kiltcs02 # BROK Setting to ignore signal %d failed. Errno: %d, Error message %s. + + WARN : + kiltcs02 0 WARN Unexpected signal X was caught. + + SPECIAL PROCEDURAL REQUIREMENTS + + The program must be linked with tst_res.o. + + DETAILED DESCRIPTION + + **Setup** + Set up unexpected signal handling. + Set up one pipe for each process to be created with no blocking for read. + + **MAIN** + If setup fails exit. + Fork 2 children(1 & 2). + Wait for set up complete messages from the 1st and 2nd child. + Send the signal SIGUSR1 with pid equal to zero. + Sleep a reasonable amount of time so that each child has been swapped in + to process the signal. + Now decide the outcome of the test items by reading from each pipe to find + out if the child was interrupted by the signal and wrote to it. + Remove the second child. + Tell the first child it is time to remove it's child B because the decisions have been made. + Exit. + + **First Child** + Set to catch SIGUSR1 with an int_rout1. + Set up to handle the message from the parent to remove child B. + Fork two children(A & B). + Wait for set up complete messages from child A & child B. + Send a set up complete message to the parent. + Pause until the signal SIGUSR1 comes in from the parent. + Pause until the parent says it is time to remove the child. + Exit. + + **Second Child** + Set to catch SIGUSR1 with an int_rout2. + Set the process group to be something different than the parents. + Send a set up complete message to the parent. + Pause until killed by parent because this child shouldn't receive signal SIGUSR1. + + **Child A** + Set to catch SIGUSR1 with an int_routA. + Send a set up complete message to the parent(First Child). + Pause until the signal SIGUSR1 comes in from the parent. + Exit. + + **Child B** + Set to catch SIGUSR1 with an int_routB. + Set the process group to be something different than the parents(First Child's). + Send a set up complete message to the parent. + Pause until killed by parent because this child shouldn't receive signal SIGUSR1. + + **usr1_rout-Used by all children** + Write to the appropriate pipe that the signal SIGUSR1 was caught. + + **usr2_rout** + Remove child B. + +******************************************************************************/ +#include <sys/param.h> +#include <signal.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include "test.h" +#include "usctest.h" + +#define MAXMESG 150 /*The maximum message that can be created. */ +#define CHAR_SET_FAILED "0" /*Set up failing status transferred through the pipe. */ +#define CHAR_SET_PASSED "1" /*Set up passing status transferred through the pipe. */ +#define SIG_CAUGHT "2" /*Indicates that the signal SIGUSR1 was caught. */ +#define SIG_RECEIVED 1 /*Integer value that indicates that the signal SIGUSR1 */ + /*was caught. */ +#define SIG_NOT_RECD 0 /*Integer value that indicates that the signal SIGUSR1 */ + /*was caught. */ +#define INT_SET_FAILED 0 /*Set up failing status transferred through the pipe. */ +#define INT_SET_PASSED 1 /*Set up passing status transferred through the pipe. */ +#define SLEEP_TIME 10 /*Amount of time the children get to catch the signal */ +#define TRUE 40 /*Child exits with this if execution was as */ + /*expected. */ +#define FALSE 50 /*Child exits with this if it timed out waiting for the */ + /*parents signal. */ +#define TIMEOUT 60 /*Amount of time given in alarm calls. */ +#define CHILD_EXIT(VAR) ((VAR >> 8) & 0377) /*Exit value from the child. */ +#define CHILD_SIG(VAR) (VAR & 0377) /*Signal value from the termination of child. */ + /*from the parent. */ +#define SYS_FAIL "The system call %s failed. Errno: %d, Error message: %s." + +int pid1; /*Return value from 1st fork. Global so that it can be */ + /*used in interrupt handling routines. */ +int pid2; /*Return value from 2nd fork. Global so that it can be */ + /*used in interrupt handling routines. */ +int pidA; /*Return value from 1st fork in child 1. Global so that it */ + /*can be used in interrupt handling routines. */ +int pidB; /*Return value from 2nd fork in child 1. Global so that it */ + /*can be used in interrupt handling routines. */ +extern int errno; /*Error number returned by a system call. */ +int pipe1_fd[2]; /*Pipe file descriptors used for communication */ + /*between child 1 and the 1st parent. */ +int pipe2_fd[2]; /*Pipe file descriptors used for communication */ + /*between child 2 and the 1st parent. */ +int pipeA_fd[2]; /*Pipe file descriptors used for communication */ + /*between child A and the 1st parent. */ +int pipeB_fd[2]; /*Pipe file descriptors used for communication */ + /*between child B and the 1st parent. */ +char pipe_buf[10]; /*Pipe buffer. */ +char buf_tmp1[2],buf_tmp2[2]; /*Temp hold for info read into pipe_buf. */ +int read1_stat = 0; /*Number of characters read from pipe 1. */ +int read2_stat = 0; /*Number of characters read from pipe 2. */ +int readA_stat = 0; /*Number of characters read from pipe A. */ +int readB_stat = 0; /*Number of characters read from pipe B. */ +int alarm_flag = FALSE; /*This flag indicates an alarm time out. */ +char who_am_i = '0'; /*This indicates which process is which when using */ + /*interrupt routine usr1_rout. */ + +void notify_timeout(); /*Signal handler that the parent enters if it times out */ + /*waiting for the child to indicate its set up status. */ +void parent_rout(); /*This is the parents routine. */ +void child1_rout(); /*This is child 1's routine. */ +void child2_rout(); /*This is child 2's routine. */ +void childA_rout(); /*This is child A's routine. */ +void childB_rout(); /*This is child B's routine. */ +void usr1_rout(); /*This routine is used by all children to indicate that */ + /*they have caught signal SIGUSR1. */ +void par_kill(); /*This routine is called by the original parent to */ + /*remove child 2 and to indicate to child 1 to */ + /*remove its children. */ +void chld1_kill(); /*This routine is used by child 1 to remove itself and */ + /*its children A and B. */ + +void setup(); +void cleanup(); + +char *TCID="kill02"; /* Test program identifier. */ +int TST_TOTAL=2; /* Total number of test cases. */ +extern int Tst_count; /* Test Case counter for tst_* routines */ +extern int Tst_nobuf; /* var. used to turn off tst_res buffering */ + +int exp_enos[]={0}; /* Array of expected errnos */ + +/*********************************************************************** + * MAIN + ***********************************************************************/ +int +main(int ac, char **av) +{ + char mesg[MAXMESG]; /* Holds messages to pass to tst_res. */ + + int lc; /* loop counter */ + const char *msg; /* message returned from parse_opts */ + + Tst_nobuf=1; + + /*************************************************************** + * parse standard options, and exit if there is an error + * the -t and -f options not support yet. + ***************************************************************/ + if ( (msg=parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *) NULL ) { + tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); + tst_exit(); + } + + /*************************************************************** + * perform global setup for test + ***************************************************************/ + setup(); + + /*************************************************************** + * check looping state if -c option given + ***************************************************************/ + for (lc=0; TEST_LOOPING(lc); lc++) { + + /* reset Tst_count in case we are looping. */ + Tst_count=0; + + if ((pid1 = fork()) > 0) + { + /* + * This is the parent, fork again to create child 2. + */ + if ((pid2 = fork()) > 0) { + /* + * This is the parent. + */ + (void) parent_rout(); + } + else if (pid2 == 0) { + /* + * This is child 2. + */ + (void) child2_rout(); + } + else { + /* + * The second fork failed kill the first child. + */ + if (kill(pid1,SIGKILL) == -1 && errno != ESRCH) { + tst_resm(TWARN,"Child process may not have been killed."); + } + (void) sprintf(mesg,SYS_FAIL,"fork",errno,strerror(errno)); + tst_brkm(TBROK,cleanup,mesg); + } + + } + else if (pid1 == 0) { + /* + * This is child 1. + */ + (void) child1_rout(); + } + else { + /* + * Fork failed. + */ + (void) sprintf(mesg,SYS_FAIL,"fork",errno,strerror(errno)); + tst_brkm(TBROK,cleanup,mesg); + } + } + + cleanup(); + + return 0; +} /* END OF MAIN.*/ + +/****************************************************************************** + * This is the parents routine. The parent waits for the children 1 and 2 to + * get set up. Then sends the signal and checks the outcome. + *********************************************************************************/ +void parent_rout() +{ + char mesg[MAXMESG]; /*Used to buffer messages for tst_resm. */ + + /* + * Set to catch the alarm signal SIGALRM. + */ + if (signal(SIGALRM,notify_timeout) == SIG_ERR) { + (void) par_kill(); + tst_brkm(TBROK, NULL, + "Could not set to catch the parents time out alarm."); + tst_exit(); + } + + /* + * Setting to catch the timeout alarm worked now let the children start up. + * Set an alarm which causes a time out on the read pipe loop. + * The children will notify the parent that set up is complete + * and the pass/fail status of set up. + */ + (void) alarm(TIMEOUT); + + while ((read(pipe1_fd[0],pipe_buf,1) != 1) && (alarm_flag == FALSE)) + /*EMPTY*/; + strncpy(buf_tmp1,pipe_buf,1); + (void) alarm(TIMEOUT); + + while ((read(pipe2_fd[0],pipe_buf,1) != 1) && (alarm_flag == FALSE)) + /*EMPTY*/; + (void) alarm(0); /*Reset the alarm clock.*/ + strncpy(buf_tmp2,pipe_buf,1); + + /* + * Check the alarm flag. + */ + if (alarm_flag == TRUE) { + tst_brkm(TBROK,NULL,"The set up of the children failed by timing out."); + (void) par_kill(); + cleanup(); + } + + /* + * Check to see if either child failed in the set up. + */ + if ( (strncmp(buf_tmp1,CHAR_SET_FAILED,1) == 0) || + (strncmp(buf_tmp2,CHAR_SET_FAILED,1) == 0)) { + /* + * Problems were encountered in the set up of one of the children. + * The error message has been displayed by the child. + */ + (void) par_kill(); + cleanup(); + } + + /* + * Setup passed, now send SIGUSR1 to process id of zero. + */ + TEST( kill(0,SIGUSR1) ); + + if ( TEST_RETURN == -1) + { + (void) sprintf(mesg,SYS_FAIL,"kill",errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + (void) par_kill(); + cleanup(); + } + + /* + * Sleep for a while to allow the children to get a chance to + * catch the signal. + */ + (void) sleep(SLEEP_TIME); + + /* + * The signal was sent above and time has run out for child response, + * check the outcomes. + */ + read1_stat = read(pipe1_fd[0],pipe_buf,1); + if (read1_stat == -1 && errno == EAGAIN) read1_stat = 0; + read2_stat = read(pipe2_fd[0],pipe_buf,1); + if (read2_stat == -1 && errno == EAGAIN) read2_stat = 0; + readA_stat = read(pipeA_fd[0],pipe_buf,1); + if (readA_stat == -1 && errno == EAGAIN) readA_stat = 0; + readB_stat = read(pipeB_fd[0],pipe_buf,1); + if (readB_stat == -1 && errno == EAGAIN) readB_stat = 0; + + if (read1_stat == -1 || read2_stat == -1 || + readA_stat == -1 || readB_stat == -1) { + /* + * The read system call failed. + */ + (void) sprintf(mesg,SYS_FAIL,"read",errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + (void) par_kill(); + cleanup(); + } + + /* + * Check the processes that were supposed to get the signal. + */ + if (read1_stat == SIG_RECEIVED) { + if (readA_stat == SIG_RECEIVED) { + /* + * Both processes, 1 and A, that were supposed to receive + * the signal did receive the signal. + */ + if ( STD_FUNCTIONAL_TEST ) + tst_resm(TPASS, + "The signal was sent to all processes in the process group."); + else + Tst_count++; + } + else { /*Process A didn't receive the signal.*/ + tst_resm(TFAIL,"Process A did not receive the signal."); + } + + } + else { /*Process 1 didn't receive the signal.*/ + tst_resm(TFAIL,"Process 1 did not receive the signal."); + } + + /* + * Check the processes that were not supposed to get the signal. + */ + if (read2_stat == SIG_NOT_RECD) { + if (readB_stat == SIG_NOT_RECD) { + /* + * Both processes, 2 and B did not receive the signal. + */ + if ( STD_FUNCTIONAL_TEST ) + tst_resm(TPASS, + "The signal was not sent to selective processes that were not in the process group."); + else + Tst_count++; + } + else { /*Process B received the signal.*/ + tst_resm(TFAIL,"Process B received the signal."); + } + + } + + else /*Process 2 received the signal.*/ + { + tst_resm(TFAIL,"Process 2 received the signal."); + } + + (void) par_kill(); + return; +} /*End of parent_rout*/ + +/******************************************************************************* + * This is child 1's routine. It creates children A & B, checks their set up, + * reports to the parent set up pass/fail info., then waits for + * the parents signal. + ******************************************************************************/ +void child1_rout() +{ + char mesg[MAXMESG]; /*Used to buffer messages for tst_resm. */ + who_am_i = '1'; + + /* + * Set to catch the SIGUSR1 with int1_rout. + */ + if (signal(SIGUSR1,usr1_rout) == SIG_ERR) + { + tst_brkm(TBROK,NULL,"Could not set to catch the childrens signal."); + (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); + exit(0); + } + + /* + * Create children A & B. + */ + if ((pidA = fork()) > 0) { + /* + * This is the parent(child1), fork again to create child B. + */ + if ((pidB = fork()) == 0) { + /* This is child B. */ + (void) childB_rout(); + } + + else if (pidB == -1) { + /* + * The fork of child B failed kill child A. + */ + if (kill(pidA,SIGKILL) == -1) + tst_resm(TWARN,"Child process may not have been killed."); + (void) sprintf(mesg,SYS_FAIL,"fork",errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + (void) write(pipe2_fd[1],CHAR_SET_FAILED,1); + exit(0); + } + } + + else if (pidA == 0) { + /* This is child A. */ + (void) childA_rout(); + + } + + else if (pidA == -1) { + /* + * The fork of child A failed. + */ + (void) sprintf(mesg,SYS_FAIL,"fork",errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); + exit(0); + } + + /* + * Set to catch the SIGUSR2 with chld1_kill. + */ + if (signal(SIGUSR2,chld1_kill) == SIG_ERR) { + tst_brkm(TBROK,NULL,"Could not set to catch the parents signal."); + (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); + (void) chld1_kill(); + exit(0); + } + + /* + * Set to catch the alarm signal SIGALRM. + */ + if (signal(SIGALRM,notify_timeout) == SIG_ERR) { + tst_brkm(TBROK,NULL,"Could not set to catch the childs time out alarm."); + (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); + (void) chld1_kill(); + exit(0); + } + + /* + * Setting to catch the signals worked now let the children start up. + * Set an alarm which causes a time out on the pipe read loop. + * The children A & B will notify the parent(child1) that set up is complete + * and the pass/fail status of set up. + */ + (void) alarm(TIMEOUT-40); + + while ((read(pipeA_fd[0],pipe_buf,1) != 1) && (alarm_flag == FALSE)) + /*EMPTY*/; + (void) alarm(TIMEOUT-40); + + while ((read(pipeB_fd[0],pipe_buf,1) != 1) && (alarm_flag == FALSE)) + /*EMPTY*/; + (void) alarm(0); /*Reset the alarm clock.*/ + + /* + * Check the alarm flag. + */ + if (alarm_flag == TRUE) { + tst_brkm(TBROK,NULL,"The set up of the children failed by timing out."); + (void) chld1_kill(); + (void) write(pipe1_fd[1],CHAR_SET_FAILED,1); + exit(0); + } + + /* + * Send a set up complete message to the parent. + */ + (void) write(pipe1_fd[1],CHAR_SET_PASSED,1); + + /* + * Pause until the signal SIGUSR1 or SIGUSR2 is sent from the parent. + */ + (void) pause(); + + /* + * Pause until signal SIGUSR2 is sent from the parent. + * This pause will only be executed if SIGUSR2 has not been received yet. + */ + while (1) { + sleep(1); + } + +} /*End of child1_rout*/ + +/******************************************************************************* + * This is the routine for child 2, which should not receive the parents signal. + ******************************************************************************/ +void child2_rout() +{ + who_am_i = '2'; + + /* + * Set the process group of this process to be different + * than the other processes. + */ + (void) setpgrp(); + + /* + * Set to catch the SIGUSR1 with usr1_rout. + */ + if (signal(SIGUSR1,usr1_rout) == SIG_ERR) { + tst_brkm(TBROK,cleanup,"Could not set to catch the parents signal."); + (void) write(pipe2_fd[1],CHAR_SET_FAILED,1); + exit(0); + } + + /* Send a set up complete message to parent.*/ + (void) write(pipe2_fd[1],CHAR_SET_PASSED,1); + + /* + * Pause until killed by the parent or SIGUSR1 is received. + */ + (void) pause(); +} + + +/******************************************************************************* + * This is the routine for child A, which should receive the parents signal. + ******************************************************************************/ +void childA_rout() +{ + who_am_i = 'A'; + + /* Send a set up complete message to parent.*/ + write(pipeA_fd[1],CHAR_SET_PASSED,1); + + /* + * Pause until killed by the parent or SIGUSR1 is received. + */ + (void) pause(); + + exit(0); +} /*End of childA_rout*/ + +/******************************************************************************* + * This is the routine for child B, which should not receive the parents signal. + ******************************************************************************/ +void childB_rout() +{ + who_am_i = 'B'; + + /* + * Set the process group of this process to be different + * than the other processes. + */ + (void) setpgrp(); + + /* Send a set up complete message to parent(child 1).*/ + write(pipeB_fd[1],CHAR_SET_PASSED,1); + + /* + * Pause until killed by the parent(child 1) or SIGUSR1 is received. + */ + (void) pause(); + + exit(0); +} + +/******************************************************************************* + * This routine sets up the interprocess communication pipes, signal handling, + * and process group information. + ******************************************************************************/ +void +setup() +{ + int errno_buf; /*indicates the errno if pipe set up fails. */ + int err_flag = FALSE; /*Indicates if an error has occurred in pipe set up. */ + char mesg[MAXMESG]; /*Used to buffer messages for tst_res. */ + + /* + * Set the process group ID to be equal between the parent and children. + */ + (void) setpgrp(); + + /* + * Set to catch unexpected signals. + * SIGCLD is set to be ignored because we do not wait for termination status. + * SIGUSR1 is set to be ignored because this is the signal we are using for + * the test and we are not concerned with the parent getting it. + */ + /* capture signals */ + tst_sig(FORK, DEF_HANDLER, cleanup); + + if (signal(SIGUSR1,SIG_IGN) == SIG_ERR) { + (void) sprintf(mesg, + "Setting to ignore signal SIGCLD failed. Errno: %d, Error message %s.", + errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + tst_exit(); + } + + if (signal(SIGCLD,SIG_IGN) == SIG_ERR) { + (void) sprintf(mesg, + "Setting to ignore signal SIGCLD failed. Errno: %d, Error message %s.", + errno,strerror(errno)); + tst_brkm(TBROK,NULL,mesg); + tst_exit(); + } + + /* Indicate which errnos are expected */ + TEST_EXP_ENOS(exp_enos); + + /* Pause if that option was specified */ + TEST_PAUSE; + + + /* + * Set up pipe1, pipe2, pipeA, and pipeB. + */ + if ((pipe(pipe1_fd) == -1) || (fcntl(pipe1_fd[0],F_SETFL,O_NDELAY) == -1)) + { + errno_buf = errno; + err_flag = TRUE; + } + + if ((pipe(pipe2_fd) == -1) || (fcntl(pipe2_fd[0],F_SETFL,O_NDELAY) == -1)) + { + errno_buf = errno; + err_flag = TRUE; + } + + if ((pipe(pipeA_fd) == -1) || (fcntl(pipeA_fd[0],F_SETFL,O_NDELAY) == -1)) + { + errno_buf = errno; + err_flag = TRUE; + } + + if ((pipe(pipeB_fd) == -1) || (fcntl(pipeB_fd[0],F_SETFL,O_NDELAY) == -1)) + { + errno_buf = errno; + err_flag = TRUE; + } + + /* + * Check for errors. + */ + if (err_flag == TRUE) + { + (void) sprintf(mesg,SYS_FAIL,"pipe",errno_buf,strerror(errno_buf)); + tst_brkm(TBROK, NULL, mesg); + tst_exit(); + } + return; + +} + +/*********************************************************** + * This routine indicates that the process caught SIGUSR1. + **********************************************************/ +void usr1_rout() +{ + char mesg[MAXMESG]; /*Used to buffer messages for tst_res. */ + + switch (who_am_i) + { + case '1': if (write(pipe1_fd[1],SIG_CAUGHT,1) == -1) + tst_resm(TWARN,"Writing signal catching status failed in child 1."); + break; + case '2': if (write(pipe2_fd[1],SIG_CAUGHT,1) == -1) + tst_resm(TWARN,"Writing signal catching status failed in child 2."); + break; + case 'A': if (write(pipeA_fd[1],SIG_CAUGHT,1) == -1) + tst_resm(TWARN,"Writing signal catching status failed in child A."); + break; + case 'B': if (write(pipeB_fd[1],SIG_CAUGHT,1) == -1) + tst_resm(TWARN,"Writing signal catching status failed in child B."); + break; + default: + sprintf(mesg,"Unexpected value %d for who_am_i in usr1_rout().",who_am_i); + tst_resm(TWARN,mesg); + break; + } + +} /*End of usr1_rout*/ + + +/*********************************************************** + * This routine handles the timeout alarm in the parent, + * which occurs when the child fails to notify the parent + * the status of set up. + **********************************************************/ +void notify_timeout() +{ + alarm_flag = TRUE; + +} /*End of notify_timeout*/ + +/*********************************************************** + * This routine handles the procedure for removing the + * children forked off during this test. + **********************************************************/ +void par_kill() +{ + char mesg[MAXMESG]; /*Used to buffer messages for tst_res. */ + /* + * Indicate to child1 that it can remove it's children and itself now. + */ + if (kill(pid1,SIGUSR2) == -1 && errno != ESRCH) + { + (void) sprintf(mesg,SYS_FAIL,"kill",errno,strerror(errno)); + tst_resm(TWARN,mesg); + tst_resm(TWARN,"Child 1 and it's children may still be alive."); + } + + /* + * Remove child 2. + */ + if (kill(pid2,SIGKILL) == -1 && errno != ESRCH) + tst_resm(TWARN,"Child2 may still be alive."); + + return; + +} /*End of par_kill*/ + + +/********************************************************************* + * This routine is executed by child 1 when the parent tells it to + * remove it's children and itself. + ********************************************************************/ +void chld1_kill() +{ + char mesg[MAXMESG]; /*Used to buffer messages for tst_resm. */ + + /* + * Remove children A & B. + */ + if (kill(pidA,SIGKILL) == -1 && errno != ESRCH) + { + (void) sprintf(mesg, + "The system call kill failed. Child 1's(A) child may still be alive. Errno: %d, Error message %s.", + errno,strerror(errno)); + tst_resm(TWARN,mesg); + } + if (kill(pidB,SIGKILL) == -1 && errno != ESRCH) + { + (void) sprintf(mesg, + "The system call kill failed. Child 1's(B) child may still be alive. Errno: %d, Error message %s.", + errno,strerror(errno)); + tst_resm(TWARN,mesg); + } + + exit(0); + +} /*End of chld1_kill*/ + +/*************************************************************** + * cleanup() - performs all ONE TIME cleanup for this test at + * completion or premature exit. + ***************************************************************/ +void +cleanup() +{ + /* + * print timing stats if that option was specified. + * print errno log if that option was specified. + */ + TEST_CLEANUP; + + /* exit with return code appropriate for results */ + tst_exit(); + +} /* End cleanup() */ + + |