| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 | /* make sure we can vfork/exec across setjmp/longjmp's * and make sure signal block masks don't get corrupted * in the process. */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <unistd.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>#include <string.h>int verbose = 0;static int execute_child(const char *prog){	int status;	pid_t child;	child = vfork();	if (child == 0) {		execlp(prog, prog, NULL);		perror("Could not execute specified prog");		_exit(1);	} else if (child == 1)		return 1;	wait(&status);	return WEXITSTATUS(status);}sigset_t orig_mask;static int check_sig_mask(void){	int status;	pid_t child;	child = vfork();	if (child == 0) {		int ret;		sigset_t child_mask;		memset(&child_mask, 0x00, sizeof(child_mask));		ret = sigprocmask(SIG_BLOCK, NULL, &child_mask);		if (ret != 0) {			perror("could not get child sig block mask");			_exit(1);		}		ret = memcmp(&orig_mask, &child_mask, sizeof(orig_mask));		if (verbose) {			printf("sigmsk: %08lx%08lx ", child_mask.__val[1], child_mask.__val[0]);			printf("sigmsk: %08lx%08lx ", orig_mask.__val[1], orig_mask.__val[0]);			printf("%i\n", ret);		}		_exit(ret);	} else if (child == 1)		return 1;	wait(&status);	return WEXITSTATUS(status);}int main(int argc, char *argv[]){	const char *prog;	jmp_buf env;	sigjmp_buf sigenv;	int max;	/* values modified between setjmp/longjmp cannot be local to this func */	static int cnt, ret;	memset(&orig_mask, 0x00, sizeof(orig_mask));	ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask);	if (ret != 0) {		perror("could not get orig sig block mask");		return 1;	}	prog = (argc > 1 ? argv[1] : "true");	ret = 0;	verbose = 0;	max = 10;	/* test vfork()/exec() inside of sigsetjmp/siglongjmp */	cnt = 0;	sigsetjmp(sigenv, 1);	++cnt;	if (verbose)		printf("sigsetjmp loop %i\n", cnt);	ret |= check_sig_mask();	ret |= execute_child(prog);	if (cnt < max)		siglongjmp(sigenv, 0);	/* test vfork()/sigprocmask() inside of setjmp/longjmp */	cnt = 0;	setjmp(env);	++cnt;	if (verbose)		printf("setjmp loop %i\n", cnt);	ret |= check_sig_mask();	ret |= execute_child(prog);	if (cnt < max)		longjmp(env, 0);	return ret;}
 |