Home | History | Annotate | Download | only in clone
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2003.
      3  * Copyright (c) 2012 Wanlong Gao <gaowanlong (at) cn.fujitsu.com>
      4  *
      5  * This program is free software; you can redistribute it and/or modify it
      6  * under the terms of version 2 of the GNU General Public License as
      7  * published by the Free Software Foundation.
      8  *
      9  * This program is distributed in the hope that it would be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  *
     13  * You should have received a copy of the GNU General Public License along
     14  * with this program; if not, write the Free Software Foundation, Inc.,
     15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16  *
     17  */
     18 /*
     19  *	This is a test for a glibc bug for the clone(2) system call.
     20  */
     21 
     22 #if defined UCLINUX && !__THROW
     23 /* workaround for libc bug */
     24 #define __THROW
     25 #endif
     26 
     27 #include <errno.h>
     28 #include <sched.h>
     29 #include <sys/wait.h>
     30 #include "test.h"
     31 #include "clone_platform.h"
     32 
     33 #define TRUE 1
     34 #define FALSE 0
     35 
     36 static void setup();
     37 static int do_child();
     38 
     39 char *TCID = "clone07";
     40 int TST_TOTAL = 1;
     41 
     42 static void sigsegv_handler(int);
     43 static void sigusr2_handler(int);
     44 static int child_pid;
     45 static int fail = FALSE;
     46 
     47 int main(int ac, char **av)
     48 {
     49 
     50 	int lc, status;
     51 	void *child_stack;
     52 
     53 	tst_parse_opts(ac, av, NULL, NULL);
     54 
     55 	setup();
     56 
     57 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     58 		tst_count = 0;
     59 		child_stack = malloc(CHILD_STACK_SIZE);
     60 		if (child_stack == NULL)
     61 			tst_brkm(TBROK, NULL,
     62 				 "Cannot allocate stack for child");
     63 
     64 		child_pid = ltp_clone(SIGCHLD, do_child, NULL,
     65 				      CHILD_STACK_SIZE, child_stack);
     66 
     67 		if (child_pid < 0)
     68 			tst_brkm(TBROK | TERRNO, NULL, "clone failed");
     69 
     70 		if ((wait(&status)) == -1)
     71 			tst_brkm(TBROK | TERRNO, NULL,
     72 				 "wait failed, status: %d", status);
     73 
     74 		free(child_stack);
     75 	}
     76 
     77 	if (fail == FALSE)
     78 		tst_resm(TPASS,
     79 			 "Use of return() in child did not cause SIGSEGV");
     80 	else
     81 		tst_resm(TFAIL, "Use of return() in child caused SIGSEGV");
     82 
     83 	tst_exit();
     84 }
     85 
     86 static void setup(void)
     87 {
     88 	struct sigaction def_act;
     89 	struct sigaction act;
     90 
     91 	TEST_PAUSE;
     92 
     93 	act.sa_handler = sigsegv_handler;
     94 	act.sa_flags = SA_RESTART;
     95 	sigemptyset(&act.sa_mask);
     96 	if ((sigaction(SIGSEGV, &act, NULL)) == -1)
     97 		tst_resm(TWARN | TERRNO,
     98 			 "sigaction() for SIGSEGV failed in test_setup()");
     99 
    100 	/* Setup signal handler for SIGUSR2 */
    101 	def_act.sa_handler = sigusr2_handler;
    102 	def_act.sa_flags = SA_RESTART | SA_RESETHAND;
    103 	sigemptyset(&def_act.sa_mask);
    104 
    105 	if ((sigaction(SIGUSR2, &def_act, NULL)) == -1)
    106 		tst_resm(TWARN | TERRNO,
    107 			 "sigaction() for SIGUSR2 failed in test_setup()");
    108 }
    109 
    110 static int do_child(void)
    111 {
    112 	return 0;
    113 }
    114 
    115 static void sigsegv_handler(int sig)
    116 {
    117 	if (child_pid == 0) {
    118 		kill(getppid(), SIGUSR2);
    119 		_exit(42);
    120 	}
    121 }
    122 
    123 /* sig_default_handler() - Default handler for parent */
    124 static void sigusr2_handler(int sig)
    125 {
    126 	if (child_pid != 0)
    127 		fail = TRUE;
    128 }
    129