📄 kill02.c
字号:
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. ******************************************************************************/voidsetup(){ 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. ***************************************************************/voidcleanup(){ /* * 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() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -