Home | History | Annotate | Download | only in pause
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  * Copyright (c) 2012 Cyril Hrubis <chrubis (at) suse.cz>
      4  *
      5  * This program is free software;  you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  * the GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program;  if not, write to the Free Software
     17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /*
     21  * Verify that, pause() returns -1 and sets errno to EINTR after receipt of a
     22  * signal which is caught by the calling process. Also, verify that the calling
     23  * process will resume execution from the point of suspension.
     24  */
     25 
     26 #include <unistd.h>
     27 #include <errno.h>
     28 #include <fcntl.h>
     29 #include <sys/wait.h>
     30 
     31 #include "test.h"
     32 
     33 char *TCID = "pause02";
     34 int TST_TOTAL = 1;
     35 static pid_t cpid;
     36 
     37 static void do_child(void);
     38 static void setup(void);
     39 static void cleanup(void);
     40 
     41 int main(int ac, char **av)
     42 {
     43 	int lc;
     44 	int status;
     45 
     46 	tst_parse_opts(ac, av, NULL, NULL);
     47 
     48 #ifdef UCLINUX
     49 	maybe_run_child(&do_child, "");
     50 #endif
     51 
     52 	setup();
     53 
     54 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     55 		tst_count = 0;
     56 
     57 		cpid = FORK_OR_VFORK();
     58 		switch (cpid) {
     59 		case -1:
     60 			tst_brkm(TBROK, cleanup, "fork() failed");
     61 		break;
     62 		case 0:
     63 #ifdef UCLINUX
     64 			if (self_exec(av[0], "") < 0)
     65 				tst_brkm(TBROK, cleanup, "self_exec failed");
     66 #else
     67 			do_child();
     68 #endif
     69 		break;
     70 		default:
     71 		break;
     72 		}
     73 
     74 		/*
     75 		 * Wait for child to enter pause().
     76 		 */
     77 		TST_PROCESS_STATE_WAIT(cleanup, cpid, 'S');
     78 
     79 		/*
     80 		 * Send the SIGINT signal now, so that child
     81 		 * returns from pause and resumes execution.
     82 		 */
     83 		kill(cpid, SIGINT);
     84 
     85 		wait(&status);
     86 
     87 		if (WIFEXITED(status)) {
     88 			if (WEXITSTATUS(status) == 0)
     89 				tst_resm(TPASS, "pause was interrupted correctly");
     90 			else
     91 				tst_resm(TFAIL, "pause was interrupted but the "
     92 				                "retval and/or errno was wrong");
     93 			continue;
     94 		}
     95 
     96 		if (WIFSIGNALED(status)) {
     97 			switch (WTERMSIG(status)) {
     98 			case SIGALRM:
     99 				tst_resm(TFAIL, "Timeout: SIGINT wasn't recieved by child");
    100 			break;
    101 			default:
    102 				tst_resm(TFAIL, "Child killed by signal");
    103 			}
    104 
    105 			continue;
    106 		}
    107 
    108 		tst_resm(TFAIL, "Pause was not interrupted");
    109 	}
    110 
    111 	cleanup();
    112 	tst_exit();
    113 }
    114 
    115 static void sig_handle(int sig)
    116 {
    117 }
    118 
    119 static void do_child(void)
    120 {
    121 	/* avoid LTP framework to do whatever it likes */
    122 	signal(SIGALRM, SIG_DFL);
    123 
    124 	if (signal(SIGINT, sig_handle) == SIG_ERR) {
    125 		fprintf(stderr, "Child: Failed to setup signal handler\n");
    126 		exit(1);
    127 	}
    128 
    129 	/* Commit suicide after 10 seconds */
    130 	alarm(10);
    131 
    132 	TEST(pause());
    133 
    134 	if (TEST_RETURN == -1) {
    135 		if (TEST_ERRNO == EINTR)
    136 			exit(0);
    137 
    138 		fprintf(stderr, "Child: Pause returned -1 but errno is %d (%s)\n",
    139 		        TEST_ERRNO, strerror(TEST_ERRNO));
    140 		exit(1);
    141 	}
    142 
    143 	fprintf(stderr, "Child: Pause returned %ld\n", TEST_RETURN);
    144 	exit(1);
    145 }
    146 
    147 static void setup(void)
    148 {
    149 	tst_sig(FORK, DEF_HANDLER, cleanup);
    150 
    151 	TEST_PAUSE;
    152 }
    153 
    154 static void cleanup(void)
    155 {
    156 }
    157