📄 signal03.c
字号:
* Deal with child's messages. * Only the GO_FLAG status will allow parent to * go on. All pipe io will be in the ipc_t structure sizes * to avoid reading part of next message. */ while ( 1 ) { while ( (rd_sz=read(fd1[0], (char *)&Ipc_info, sizeof(Ipc_info))) != 0 ) { if ( rd_sz > 0 ) break; /* read something */ } if ( rd_sz == 0 ) { /* if EOF encountered */ sprintf(mesg, "child's pipe is closed before 'go' message received"); tst_resm(TBROK, Ipc_info.mesg); tst_resm(TBROK, Ipc_info.mesg); close(fd1[0]); return; } else if ( Ipc_info.status == GO_FLAG ) { break; /* go on */ } else if ( Ipc_info.status == ERROR_FLAG ) { tst_resm(TBROK, "From child: %s", Ipc_info.mesg); tst_resm(TBROK, "From child: %s", Ipc_info.mesg); close(fd1[0]); return; } else if ( Ipc_info.status == PASS_FLAG ) { if ( STD_FUNCTIONAL_TEST ) tst_resm(TPASS, "From child: %s", Ipc_info.mesg); else Tst_count++; update_timings(Ipc_info.timings); } else if ( Ipc_info.status == FAIL_FLAG ) { tst_resm(TFAIL, "From child: %s", Ipc_info.mesg); update_timings(Ipc_info.timings); } else { tst_resm(TINFO, "Unknown message from child: %s", mesg); } } /* * Send the signal SIGKILL to the child. */ if (kill(Pid,SIGKILL) == -1) { /* * The kill system call failed. */ sprintf(mesg, "kill(Pid,SIGKILL) failed, Errno: %d, Error message: %s", errno,strerror(errno)); tst_resm(TBROK,mesg); tst_resm(TBROK,mesg); close(fd1[0]); return; } /* * Wait for the child to terminate and check the termination status. */ if (wait(&term_stat) == -1) { /* * The wait system call failed. */ sprintf(mesg, "Wait system call failed. Errno: %d, Error message: %s", errno,strerror(errno)); tst_resm(TBROK,mesg); tst_resm(TBROK,mesg); close(fd1[0]); return; } else if ( STD_FUNCTIONAL_TEST ) { if ((term_stat & 0377) == SIGKILL) { /* * The child was killed by the signal sent, * which is correct. */ tst_resm(TPASS,"The child was killed by SIGKILL."); } else if ( (term_stat >> 8) == TIMED_OUT ) { sprintf(mesg, "child exited with a timed out exit status"); tst_resm(TBROK,mesg); } else { if ((term_stat >> 8) == SIG_IGNORED && test_case == IGNORE_TEST ) { sprintf(mesg, "SIGKILL was ignored by child after sent by parent."); } else if ((term_stat >> 8) == SIG_CAUGHT && test_case == CATCH_TEST ) { sprintf(mesg, "SIGKILL was caught by child after sent by parent."); } else { sprintf(mesg, "Child's termination status is unexpected. Status: %d (%#o).", term_stat, term_stat); } tst_resm(TFAIL, mesg); } } else { Tst_count++; /* increment test counter */ } close(fd1[0]); } /* End of parent. */ else if (Pid == 0) { /* * This is the child. * Set up to ignore/catch SIGKILL and check the return values. */ errno=0; if ( test_case == IGNORE_TEST ) { exit_val = SIG_IGNORED; strcpy(string, "signal(SIGKILL, SIG_IGN)"); Tret=(long)signal(SIGKILL, SIG_IGN); TEST_ERRNO=errno; } else { exit_val = SIG_NOT_CAUGHT; strcpy(string, "signal(SIGKILL, catchsig)"); Tret=(long)signal(SIGKILL, catchsig); TEST_ERRNO=errno; } Ipc_info.timings=tblock; if ( (SIG_PF)Tret == SIG_ERR ) { if ( TEST_ERRNO == EINVAL ) { sprintf(Ipc_info.mesg, "%s ret:%ld SIG_ERR (%ld) as expected", string, Tret, (long)SIG_ERR); Ipc_info.status = PASS_FLAG; } else { sprintf(Ipc_info.mesg, "%s ret:%ld, errno:%d expected ret:%ld, errno:%d", string, Tret, TEST_ERRNO, (long)SIG_ERR, EINVAL); Ipc_info.status = FAIL_FLAG; } write(fd1[1], (char *)&Ipc_info, sizeof(Ipc_info)); } else { /* * The child was not allowed to set the signal to * be ignored and errno was correct. */ sprintf(Ipc_info.mesg, "%s ret:%ld, errno:%d expected ret:%ld, errno:%d", string, Tret, TEST_ERRNO, (long)SIG_ERR, EINVAL); Ipc_info.status = FAIL_FLAG; write(fd1[1], (char *)&Ipc_info, sizeof(Ipc_info)); } /* * tell parent we are ready - setup by child is done */ Ipc_info.status = GO_FLAG; write(fd1[1], (char *)&Ipc_info, sizeof(Ipc_info)); /* * Set the alarm to wake up from the pause below if * the parents signal is ignored. */ signal(SIGALRM, p_timeout_handler); alarm(TIMEOUT); /* * Pause until the parent sends a signal or until alarm is received. */ pause(); exit(exit_val); } /* End of child. */ else { /* * The fork system call failed. */ sprintf(mesg, "Fork system call failed. Errno: %d, Error message: %s", errno,strerror(errno)); tst_resm(TBROK,mesg); tst_resm(TBROK,mesg); close(fd1[0]); close(fd1[1]); return; }} /* End of do_test. *//*********************************************************************** * sigdfl_test - test for attempt to set SIGKILL to default ***********************************************************************/voidsigdfl_test(){ /* * Try to set SIGKILL to default and check the return values. */ errno=-4; Tret=(long)signal(SIGKILL,SIG_DFL); TEST_RETURN=Tret; TEST_ERRNO=errno; if ( (SIG_PF)TEST_RETURN == SIG_ERR ) { if ( STD_FUNCTIONAL_TEST ) { if ( TEST_ERRNO != EINVAL ) { sprintf(mesg, "signal(SIGKILL,SIG_DFL) ret:%d, errno:%d expected ret:-1, errno:%d", TEST_RETURN, TEST_ERRNO, EINVAL); tst_resm(TFAIL, mesg); } else { sprintf(mesg, "signal(SIGKILL,SIG_DFL) ret:%d, errno:%d as expected.", TEST_RETURN, TEST_ERRNO); tst_resm(TPASS, mesg); } } else Tst_count++; } else { sprintf(mesg, "signal(SIGKILL,SIG_DFL) ret:%d, errno:%d expected ret:-1, errno:%d", TEST_RETURN, TEST_ERRNO, EINVAL); tst_resm(TFAIL, mesg); }} /* End of sigdfl_test. *//*************************************************************** * setup() - performs all ONE TIME setup for this test. ***************************************************************/voidsetup(){ /* capture signals */ tst_sig(FORK, DEF_HANDLER, cleanup); /* make and change to a temporary directory */ tst_tmpdir(); /* Pause if that option was specified */ TEST_PAUSE;} /* End setup() *//*************************************************************** * 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; /* * remove the temporary directory and exit with * return code appropriate for results */ tst_rmdir(); tst_exit();} /* End cleanup() *//*********************************************************************** * Signal handler routine that used by the parent to handler * a time out situation. It will attempt to kill the child and * call cleanup. ***********************************************************************/voidp_timeout_handler(){ kill(Pid, SIGKILL); cleanup();}/*********************************************************************** * Signal handler routine that used by the child to handle * a time out situation. It will set a global varaible and return * if called. ***********************************************************************/voidc_timeout_handler(){ exit_val = TIMED_OUT; return;}/*********************************************************************** * This signal handling routine will set a global variable and return * if called. ***********************************************************************/voidcatchsig(){ exit_val = SIG_CAUGHT; return;}/*********************************************************************** * Update timing information ***********************************************************************/voidupdate_timings(atblock)struct tblock atblock;{ tblock.tb_max += atblock.tb_max; tblock.tb_min += atblock.tb_min; tblock.tb_total += atblock.tb_total; tblock.tb_count += atblock.tb_count;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -