Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Duda <deo@logos-m.ru>2001-09-09 17:38:17 +0400
committerEgor Duda <deo@logos-m.ru>2001-09-09 17:38:17 +0400
commitd961def403a334176adb4c79cb02385bfca230e7 (patch)
tree3863580db025e747aa1a5cf6f69fa0be5894e426 /winsup/testsuite/winsup.api/ltp/signal03.c
parent92ef5188af2deecd2054462bf940f6460d127fe9 (diff)
* winsup.api/ltp/dup03.c: New test.
* winsup.api/ltp/lseek03.c: Ditto. * winsup.api/ltp/mmap001.c: Ditto. * winsup.api/ltp/read01.c: Ditto. * winsup.api/ltp/readdir01.c: Ditto. * winsup.api/ltp/rmdir05.c: Ditto. * winsup.api/ltp/sbrk01.c: Ditto. * winsup.api/ltp/select02.c: Ditto. * winsup.api/ltp/select03.c: Ditto. * winsup.api/ltp/signal03.c: Ditto. * winsup.api/ltp/stat06.c: Ditto. * winsup.api/ltp/unlink08.c: Ditto. * winsup.api/known_bugs.tcl: Update to reflect new test's known failures. * winsup.api/winsup.exp: Don't delete executable in case of unexpected pass, as well as in case of unexpected failure. * README: Update paragraph about expected failures.
Diffstat (limited to 'winsup/testsuite/winsup.api/ltp/signal03.c')
-rw-r--r--winsup/testsuite/winsup.api/ltp/signal03.c665
1 files changed, 665 insertions, 0 deletions
diff --git a/winsup/testsuite/winsup.api/ltp/signal03.c b/winsup/testsuite/winsup.api/ltp/signal03.c
new file mode 100644
index 000000000..38ba72b3c
--- /dev/null
+++ b/winsup/testsuite/winsup.api/ltp/signal03.c
@@ -0,0 +1,665 @@
+/*
+ * 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. Eagan, Minnesota
+ *
+ * TEST IDENTIFIER : signal03 Boundary value and other invalid value checking
+ * of signal setup and signal sending.
+ *
+ * PARENT DOCUMENT : sgntds01 Signal System Call
+ *
+ * AUTHOR : Dave Baumgartner
+ * : Rewrote 12/92 by Richard Logan
+ *
+ * CO-PILOT : Barrie Kletscher
+ *
+ * DATE STARTED : 10/17/85
+ *
+ * TEST ITEMS
+ *
+ * 1. SIGKILL can not be set to be caught, errno:EINVAL (POSIX).
+ * 2. SIGKILL can not be caught.
+ * 3. SIGKILL can not be set to be ignored, errno:EINVAL (POSIX).
+ * 4. SIGKILL can not be ignored.
+ * 5. SIGKILL can not be reset to default, errno:EINVAL (POSIX.
+ *
+ * ENVIRONMENTAL NEEDS
+ *
+ * NONE
+ *
+ * SPECIAL PROCEDURAL REQUIREMENTS
+ *
+ * None
+ *
+ * INTERCASE DEPENDENCIES
+ *
+ * 2 depends on 1 and 4 on 3.
+ *
+ * DETAILED DESCRIPTION
+ *
+ * main()
+ * Call catch_test to test setup and catching of SIGKILL.
+ *
+ *
+ * Call ignore_test to test setup and ignoring of SIGKILL.
+ *
+ *
+ * Call sigdfl_test to test setting SIGKILL to default.
+ *
+ * * END OF MAIN *
+ *
+ *
+ * catch_test()
+ *
+ * fork a child
+ * if this is the parent
+ * sleep to let child start.
+ * send sig to child.
+ * wait for the child to terminate.
+ *
+ * if the termination status of the child equals the signal sent to it
+ * Test item 1 PASSED the child was killed.
+ * else if status equals the exit value of SIG_CAUGHT
+ * Test item 2 FAILED sig was caught.
+ * else
+ * Test item 2 FAILED because the child was not killed
+ * but sig was not caught either.
+ *
+ * else this the child
+ * set exit_val to SIG_NOT_CAUGHT.
+ * set to catch sig, where the interrupt routine just sets
+ * exit_val to SIG_CAUGHT.
+ *
+ * If the return value and errno, after trying to set to catch sig,
+ * do not indicate that an error has occurred.
+ * Test item 1 FAILED bad return, return value:X, errno:X.
+ * else
+ * Test item 1 PASSED sig was not set to be caught.
+ *
+ * pause until the parent sends a signal.
+ * The child should be killed by the signal but if not exit
+ * with exit_val.
+ *
+ * * End of catch_test. *
+ *
+ *
+ * ignore_test()
+ *
+ * fork a child
+ * if this is the parent
+ * sleep to let child start.
+ * send SIGKILL to child.
+ * wait for the child to terminate.
+ *
+ * if the termination status of the child equals SIGKILL
+ * Test item 4 PASSED the child was killed.
+ * else if the status equals the exit value of SIG_IGNORED
+ * Test item 4 FAILED SIGKILL was ignored.
+ *
+ * else this the child
+ *
+ * If the return value and errno, after trying to set to ignore SIGKILL,
+ * do not indicate that an error has occurred.
+ * Test item 3 FAILED bad return, return value:X, errno:X.
+ * else
+ * Test item 3 PASSED SIGKILL was not set to be ignored.
+ *
+ * pause until the parent sends SIGKILL.
+ * The child should be killed by the signal but if not exit
+ * with SIG_IGNORED.
+ *
+ * * End of ignore_test. *
+ *
+ *
+ * sigdfl_test()
+ *
+ * If the return value and errno, after trying to set to SIGKILL to default,
+ * do not indicate that an error has occurred.
+ * Test item 5 FAILED bad return, return value:X, errno:X.
+ * else
+ * Test item 5 PASSED SIGKILL was not set to default.
+ *
+ * * End of sigdfl_test. *
+ *
+ * BUGS/NOTES
+ * Since the system call under test is executed in the child, no
+ * timings on this system call will be reported.
+ *
+***********************************************************************************/
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include "test.h"
+#include "usctest.h"
+
+void setup();
+void cleanup();
+void do_test();
+void sigdfl_test();
+void update_timings();
+
+#if defined(linux)
+# define SIG_PF sig_t /* This might need to be sighandler_t on some systems */
+#elif defined(__CYGWIN__)
+typedef void (*sighandler_t) (int);
+#define SIG_PF sighandler_t
+#endif
+
+#define SIG_CAUGHT 1
+#define SIG_NOT_CAUGHT 0
+#define SIG_IGNORED 5
+#define TIMED_OUT 99
+
+#define TIMEOUT 20
+
+#define GO_FLAG 1
+#define ERROR_FLAG 2
+#define PASS_FLAG 3
+#define FAIL_FLAG 4
+
+#define IGNORE_TEST 1
+#define CATCH_TEST 2
+
+#define MAXMESG 150 /* The Maximum message that can be created. */
+
+int exit_val; /* Global variable, used to tell whether the */
+ /* child exited instead of being killed. */
+extern int errno; /* errno holds the error value returned by */
+ /* a system call. */
+char mesg[MAXMESG]; /* Holds messages to pass to tst_res. */
+
+struct ipc_t {
+ int status;
+ char mesg[MAXMESG];
+ struct tblock timings;
+} Ipc_info;
+
+char *TCID = "signal03";
+int TST_TOTAL = 5;
+extern int Tst_count; /* count of test items completed */
+
+int Pid; /* Return value from fork. */
+
+long Tret;
+
+/***********************************************************************
+ * M A I N
+ ***********************************************************************/
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int lc;
+ const char *msg;
+
+ /***************************************************************
+ * parse standard options
+ ***************************************************************/
+ if ( (msg=parse_opts(argc, argv, (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;
+
+ errno=-4;
+
+ /*
+ * Call catch_test to test setup and catching of SIGKILL.
+ */
+ (void) do_test(CATCH_TEST, Tst_count);
+
+ /*
+ * Call ignore_test to test setup and ignoring of SIGKILL.
+ */
+ (void) do_test(IGNORE_TEST, Tst_count);
+
+ /*
+ * Call sigdfl_test to test setting SIGKILL to default.
+ */
+ (void) sigdfl_test();
+
+ }
+
+ cleanup();
+
+ return 0;
+} /*End of main*/
+
+/***********************************************************************
+ *
+ ***********************************************************************/
+void
+do_test(test_case, tst_count)
+int test_case;
+int tst_count;
+{
+ int term_stat; /* Termination status of the child returned to */
+ /* the parent. */
+ char string[30];
+ int fd1[2]; /* ipc */
+ int rd_sz; /* size of read */
+ void p_timeout_handler();
+ void c_timeout_handler();
+ void catchsig();
+
+ Tst_count = tst_count;
+
+ /*
+ * Create a pipe of ipc
+ */
+ if ( pipe(fd1) == -1 ) {
+ sprintf(mesg,
+ "pipe system call failed, Errno: %d, Error message: %s",
+ errno,strerror(errno));
+ tst_resm(TBROK,mesg);
+ tst_resm(TBROK,mesg);
+ return;
+ }
+
+ /*
+ * Cause the read to return 0 once EOF is encountered and the
+ * read to return -1 if pipe is empty.
+ */
+
+ if ( fcntl(fd1[0], F_SETFL, O_NONBLOCK) == -1 ) {
+ sprintf(mesg, "fcntl(fd1[0], F_SETFL, O_NONBLOCK) failed: errno=%d",
+ errno);
+ tst_resm(TBROK,mesg);
+ tst_resm(TBROK,mesg);
+ close(fd1[0]);
+ close(fd1[1]);
+ return;
+ }
+
+ if ((Pid = fork()) > 0) { /* parent */
+
+ signal(SIGALRM, p_timeout_handler);
+
+ alarm(TIMEOUT);
+
+ close(fd1[1]); /* close write side */
+
+ /*
+ * 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
+ ***********************************************************************/
+void
+sigdfl_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.
+ ***************************************************************/
+void
+setup()
+{
+ /* 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.
+ ***************************************************************/
+void
+cleanup()
+{
+
+ /*
+ * 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.
+ ***********************************************************************/
+void
+p_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.
+ ***********************************************************************/
+void
+c_timeout_handler()
+{
+ exit_val = TIMED_OUT;
+ return;
+}
+
+/***********************************************************************
+ * This signal handling routine will set a global variable and return
+ * if called.
+ ***********************************************************************/
+void
+catchsig()
+{
+ exit_val = SIG_CAUGHT;
+ return;
+}
+
+/***********************************************************************
+ * Update timing information
+ ***********************************************************************/
+void
+update_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;
+}