svn commit: r310890 - head/usr.sbin/syslogd

Hiroki Sato hrs at FreeBSD.org
Sat Dec 31 06:23:06 UTC 2016


Author: hrs
Date: Sat Dec 31 06:23:05 2016
New Revision: 310890
URL: https://svnweb.freebsd.org/changeset/base/310890

Log:
  Replace two fat signal handlers with function calls in
  the main I/O multiplex loop.  select() now watches
  a pipe which is written by the new skinny signal
  handlers and the received signals are handled inside
  the loop sequencially.
  
  This eliminates a complex signal mask to guarantee
  async-signal safety.

Modified:
  head/usr.sbin/syslogd/syslogd.c

Modified: head/usr.sbin/syslogd/syslogd.c
==============================================================================
--- head/usr.sbin/syslogd/syslogd.c	Sat Dec 31 06:07:48 2016	(r310889)
+++ head/usr.sbin/syslogd/syslogd.c	Sat Dec 31 06:23:05 2016	(r310890)
@@ -321,8 +321,9 @@ static int	LogFacPri;	/* Put facility an
 static int	KeepKernFac;	/* Keep remotely logged kernel facility */
 static int	needdofsync = 0; /* Are any file(s) waiting to be fsynced? */
 static struct pidfh *pfh;
+static int	sigp[2];	/* Pipe to catch a signal during select(). */
 
-static volatile sig_atomic_t MarkSet, WantDie;
+static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild;
 
 static int	allowaddr(char *);
 static int	addfile(struct filed *);
@@ -340,6 +341,7 @@ static void	dofsync(void);
 static void	domark(int);
 static void	fprintlog(struct filed *, int, const char *);
 static void	init(int);
+static void	init_sh(int);
 static void	logerror(const char *);
 static void	logmsg(int, const char *, const char *, int);
 static void	log_deadchild(pid_t, int, const char *);
@@ -347,11 +349,13 @@ static void	markit(void);
 static int	socksetup(struct peer *);
 static int	socklist_recv_file(struct socklist *);
 static int	socklist_recv_sock(struct socklist *);
+static int	socklist_recv_signal(struct socklist *);
 static int	skip_message(const char *, const char *, int);
 static void	printline(const char *, char *, int);
 static void	printsys(char *);
 static int	p_open(const char *, pid_t *);
 static void	reapchild(int);
+static void	reapchild_sh(int);
 static const char *ttymsg_check(struct iovec *, int, char *, int);
 static void	usage(void);
 static int	validate(struct sockaddr *, const char *);
@@ -435,7 +439,6 @@ main(int argc, char *argv[])
 	struct timeval tv, *tvp;
 	struct peer *pe;
 	struct socklist *sl;
-	sigset_t mask;
 	pid_t ppid = 1, spid;
 	char *p;
 
@@ -578,6 +581,17 @@ main(int argc, char *argv[])
 	if ((argc -= optind) != 0)
 		usage();
 
+	/* Pipe to catch a signal during select(). */
+	s = pipe2(sigp, O_NONBLOCK);
+	if (s < 0) {
+		err(1, "cannot open a pipe for signals");
+	} else {
+		addsock(NULL, 0, &(struct socklist){
+		    .sl_socket = sigp[1],
+		    .sl_recv = socklist_recv_signal
+		});
+	}
+
 	/* Listen by default: /dev/klog. */
 	s = open(_PATH_KLOG, O_RDONLY|O_NONBLOCK, 0);
 	if (s < 0) {
@@ -632,19 +646,8 @@ main(int argc, char *argv[])
 	(void)signal(SIGTERM, dodie);
 	(void)signal(SIGINT, Debug ? dodie : SIG_IGN);
 	(void)signal(SIGQUIT, Debug ? dodie : SIG_IGN);
-	/*
-	 * We don't want the SIGCHLD and SIGHUP handlers to interfere
-	 * with each other; they are likely candidates for being called
-	 * simultaneously (SIGHUP closes pipe descriptor, process dies,
-	 * SIGCHLD happens).
-	 */
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGHUP);
-	(void)sigaction(SIGCHLD, &(struct sigaction){
-	    .sa_handler = reapchild,
-	    .sa_mask = mask,
-	    .sa_flags = SA_RESTART
-	}, NULL);
+	(void)signal(SIGHUP, init_sh);
+	(void)signal(SIGCHLD, reapchild_sh);
 	(void)signal(SIGALRM, domark);
 	(void)signal(SIGPIPE, SIG_IGN);	/* We'll catch EPIPE instead. */
 	(void)alarm(TIMERINTVL);
@@ -654,16 +657,6 @@ main(int argc, char *argv[])
 
 	dprintf("off & running....\n");
 
-	init(0);
-	/* prevent SIGHUP and SIGCHLD handlers from running in parallel */
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGCHLD);
-	(void)sigaction(SIGHUP, &(struct sigaction){
-	    .sa_handler = init,
-	    .sa_mask = mask,
-	    .sa_flags = SA_RESTART
-	}, NULL);
-
 	tvp = &tv;
 	tv.tv_sec = tv.tv_usec = 0;
 
@@ -677,6 +670,12 @@ main(int argc, char *argv[])
 		errx(1, "calloc fd_set");
 
 	for (;;) {
+		if (Initialized == 0)
+			init(0);
+		else if (WantInitialize)
+			init(WantInitialize);
+		if (WantReapchild)
+			reapchild(WantReapchild);
 		if (MarkSet)
 			markit();
 		if (WantDie)
@@ -716,6 +715,19 @@ main(int argc, char *argv[])
 }
 
 static int
+socklist_recv_signal(struct socklist *sl __unused)
+{
+	ssize_t len;
+	static char buf[BUFSIZ];
+
+	/* Clear an wake-up signal by reading dummy data. */
+	while ((len = read(sigp[0], buf, sizeof(buf))) > 0)
+		;
+
+	return (0);
+}
+
+static int
 socklist_recv_sock(struct socklist *sl)
 {
 	struct sockaddr_storage ss;
@@ -987,7 +999,7 @@ static void
 logmsg(int pri, const char *msg, const char *from, int flags)
 {
 	struct filed *f;
-	int i, fac, msglen, omask, prilev;
+	int i, fac, msglen, prilev;
 	const char *timestamp;
  	char prog[NAME_MAX+1];
 	char buf[MAXLINE+1];
@@ -995,8 +1007,6 @@ logmsg(int pri, const char *msg, const c
 	dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
 	    pri, flags, from, msg);
 
-	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
-
 	/*
 	 * Check to see if msg looks non-standard.
 	 */
@@ -1027,10 +1037,8 @@ logmsg(int pri, const char *msg, const c
 		fac = LOG_FAC(pri);
 
 	/* Check maximum facility number. */
-	if (fac > LOG_NFACILITIES) {
-		(void)sigsetmask(omask);
+	if (fac > LOG_NFACILITIES)
 		return;
-	}
 
 	prilev = LOG_PRI(pri);
 
@@ -1067,7 +1075,6 @@ logmsg(int pri, const char *msg, const c
 			close(f->f_file);
 			f->f_file = -1;
 		}
-		(void)sigsetmask(omask);
 		return;
 	}
 	STAILQ_FOREACH(f, &fhead, next) {
@@ -1139,7 +1146,6 @@ logmsg(int pri, const char *msg, const c
 			}
 		}
 	}
-	(void)sigsetmask(omask);
 }
 
 static void
@@ -1507,6 +1513,17 @@ ttymsg_check(struct iovec *iov, int iovc
 }
 
 static void
+reapchild_sh(int signo)
+{
+	static char buf[BUFSIZ];
+
+	WantReapchild = signo;
+	/* Send an wake-up signal to the select() loop. */
+	read(sigp[0], buf, sizeof(buf));
+	write(sigp[1], &signo, sizeof(signo));
+}
+
+static void
 reapchild(int signo __unused)
 {
 	int status;
@@ -1514,10 +1531,6 @@ reapchild(int signo __unused)
 	struct filed *f;
 
 	while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
-		if (!Initialized)
-			/* Don't tell while we are initting. */
-			continue;
-
 		/* First, look if it's a process from the dead queue. */
 		if (deadq_removebypid(pid))
 			continue;
@@ -1532,6 +1545,7 @@ reapchild(int signo __unused)
 			}
 		}
 	}
+	WantReapchild = 0;
 }
 
 /*
@@ -1541,7 +1555,6 @@ static const char *
 cvthname(struct sockaddr *f)
 {
 	int error, hl;
-	sigset_t omask, nmask;
 	static char hname[NI_MAXHOST], ip[NI_MAXHOST];
 
 	dprintf("cvthname(%d) len = %d\n", f->sa_family, f->sa_len);
@@ -1556,12 +1569,8 @@ cvthname(struct sockaddr *f)
 	if (!resolve)
 		return (ip);
 
-	sigemptyset(&nmask);
-	sigaddset(&nmask, SIGHUP);
-	sigprocmask(SIG_BLOCK, &nmask, &omask);
 	error = getnameinfo(f, f->sa_len, hname, sizeof(hname),
 		    NULL, 0, NI_NAMEREQD);
-	sigprocmask(SIG_SETMASK, &omask, NULL);
 	if (error) {
 		dprintf("Host name for your address (%s) unknown\n", ip);
 		return (ip);
@@ -1616,11 +1625,8 @@ die(int signo)
 {
 	struct filed *f;
 	struct socklist *sl;
-	int was_initialized;
 	char buf[100];
 
-	was_initialized = Initialized;
-	Initialized = 0;	/* Don't log SIGCHLDs. */
 	STAILQ_FOREACH(f, &fhead, next) {
 		/* flush any pending output */
 		if (f->f_prevcount)
@@ -1628,7 +1634,6 @@ die(int signo)
 		if (f->f_type == F_PIPE && f->fu_pipe_pid > 0)
 			close_filed(f);
 	}
-	Initialized = was_initialized;
 	if (signo) {
 		dprintf("syslogd: exiting on signal %d\n", signo);
 		(void)snprintf(buf, sizeof(buf), "exiting on signal %d", signo);
@@ -1793,6 +1798,17 @@ readconfigfile(FILE *cf, int allow_inclu
  *  INIT -- Initialize syslogd from configuration table
  */
 static void
+init_sh(int signo)
+{
+	static char buf[BUFSIZ];
+
+	WantInitialize = signo;
+	/* Send an wake-up signal to the select() loop. */
+	read(sigp[0], buf, sizeof(buf));
+	write(sigp[1], &signo, sizeof(signo));
+}
+
+static void
 init(int signo)
 {
 	int i;
@@ -1804,6 +1820,7 @@ init(int signo)
 	char bootfileMsg[LINE_MAX];
 
 	dprintf("init\n");
+	WantInitialize = 0;
 
 	/*
 	 * Load hostname (may have changed).
@@ -2669,7 +2686,6 @@ p_open(const char *prog, pid_t *rpid)
 {
 	int pfd[2], nulldesc;
 	pid_t pid;
-	sigset_t omask, mask;
 	char *argv[4]; /* sh -c cmd NULL */
 	char errmsg[200];
 
@@ -2679,17 +2695,13 @@ p_open(const char *prog, pid_t *rpid)
 		/* we are royally screwed anyway */
 		return (-1);
 
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGALRM);
-	sigaddset(&mask, SIGHUP);
-	sigprocmask(SIG_BLOCK, &mask, &omask);
 	switch ((pid = fork())) {
 	case -1:
-		sigprocmask(SIG_SETMASK, &omask, 0);
 		close(nulldesc);
 		return (-1);
 
 	case 0:
+		(void)setsid();	/* Avoid catching SIGHUPs. */
 		argv[0] = strdup("sh");
 		argv[1] = strdup("-c");
 		argv[2] = strdup(prog);
@@ -2700,19 +2712,11 @@ p_open(const char *prog, pid_t *rpid)
 		}
 
 		alarm(0);
-		(void)setsid();	/* Avoid catching SIGHUPs. */
 
-		/*
-		 * Throw away pending signals, and reset signal
-		 * behaviour to standard values.
-		 */
-		signal(SIGALRM, SIG_IGN);
-		signal(SIGHUP, SIG_IGN);
-		sigprocmask(SIG_SETMASK, &omask, 0);
-		signal(SIGPIPE, SIG_DFL);
-		signal(SIGQUIT, SIG_DFL);
-		signal(SIGALRM, SIG_DFL);
-		signal(SIGHUP, SIG_DFL);
+		/* Restore signals marked as SIG_IGN. */
+		(void)signal(SIGINT, SIG_DFL);
+		(void)signal(SIGQUIT, SIG_DFL);
+		(void)signal(SIGPIPE, SIG_DFL);
 
 		dup2(pfd[0], STDIN_FILENO);
 		dup2(nulldesc, STDOUT_FILENO);
@@ -2722,8 +2726,6 @@ p_open(const char *prog, pid_t *rpid)
 		(void)execvp(_PATH_BSHELL, argv);
 		_exit(255);
 	}
-
-	sigprocmask(SIG_SETMASK, &omask, 0);
 	close(nulldesc);
 	close(pfd[0]);
 	/*


More information about the svn-src-head mailing list