171 lines · 2.9 KB · C
RawDownload
#include <u.h>#include <sys/time.h>#include <sys/resource.h>#include "threadimpl.h" #undef waitpid#undef pipe#undef wait static int sigpid;static int threadpassfd;static int gotsigchld; static voidchild(void){	int status, pid;	struct rlimit rl; 	notedisable("sys: child");	pid = waitpid(sigpid, &status, 0);	if(pid < 0){		fprint(2, "%s: wait: %r\n", argv0);		_exit(97);	}	if(WIFEXITED(status))		 _exit(WEXITSTATUS(status));	if(WIFSIGNALED(status)){		/*		 * Make sure we don't scribble over the nice		 * core file that our child just wrote out.		 */		rl.rlim_cur = 0;		rl.rlim_max = 0;		setrlimit(RLIMIT_CORE, &rl); 		signal(WTERMSIG(status), SIG_DFL);		raise(WTERMSIG(status));		_exit(98);	/* not reached */	}	if(WIFSTOPPED(status)){		fprint(2, "%s: wait pid %d stopped\n", argv0, pid);		return;	}#ifdef WIFCONTINUED	if(WIFCONTINUED(status)){		fprint(2, "%s: wait pid %d continued\n", argv0, pid);		return;	}#endif	fprint(2, "%s: wait pid %d status 0x%ux\n", argv0, pid, status);	_exit(99);} static voidsigpass(int sig){	if(sigpid == 1){		gotsigchld = 1;		return;	} 	if(sig == SIGCHLD)		child();	else		kill(sigpid, sig);} static int sigs[] = {	SIGHUP, SIGINT, SIGQUIT, SIGILL,	SIGTRAP, SIGABRT, SIGBUS, SIGFPE,	SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,	SIGALRM, SIGTERM, SIGCHLD, SIGSTOP,	/*SIGTSTP, SIGTTIN, SIGTTOU,*/ SIGURG, 	SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF,#ifdef SIGWINCH	SIGWINCH,#endif#ifdef SIGIO	SIGIO,#endif#ifdef SIGEMT	SIGEMT,#endif#ifdef SIGPWR	SIGPWR, #endif#ifdef SIGINFO	SIGINFO,#endif	SIGSYS}; void_threadsetupdaemonize(void){	int i, n, pid;	int p[2];	char buf[20]; 	sigpid = 1; 	if(pipe(p) < 0)		sysfatal("passer pipe: %r"); 	/* hide these somewhere they won't cause harm */	/* can't go too high: NetBSD max is 64, for example */	if(dup(p[0], 28) < 0 || dup(p[1], 29) < 0)		sysfatal("passer pipe dup: %r");	close(p[0]);	close(p[1]);	p[0] = 28;	p[1] = 29; 	/* close on exec */	if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0)		sysfatal("passer pipe pipe fcntl: %r"); 	noteenable("sys: child");	signal(SIGCHLD, sigpass);	switch(pid = fork()){	case -1:		sysfatal("passer fork: %r");	default:		close(p[1]);		break;	case 0:		notedisable("sys: child");		signal(SIGCHLD, SIG_DFL);	/*	rfork(RFNOTEG); */		close(p[0]);		threadpassfd = p[1];		return;	} 	sigpid = pid;	if(gotsigchld)		sigpass(SIGCHLD); 	for(i=0; i<nelem(sigs); i++){		struct sigaction sa; 		memset(&sa, 0, sizeof sa);		sa.sa_handler = sigpass;		sa.sa_flags |= SA_RESTART;		sigaction(sigs[i], &sa, nil);	} 	for(;;){		n = read(p[0], buf, sizeof buf-1);		if(n == 0){	/* program exited */			child();		}		if(n > 0)			break;		print("passer read: %r\n");	}	buf[n] = 0;	_exit(atoi(buf));} void_threaddaemonize(void){	if(threadpassfd >= 0){		write(threadpassfd, "0", 1);		close(threadpassfd);		threadpassfd = -1;	}}