put on my flame resistant suit and tempt fate by attempting to fix some of

the races in my previous commits here, and fix some other problems with
syslogd as well.

- if the child process exited early (eg: could not bind to the socket),
  the boot process would hang for 30 seconds.  The parent was not noticing
  that the child had exited.  (my fault)
- when writing to tty devices, instead of treating them like files that
  need \r\n instead of \n, actually use ttymsg() which has specific code
  intended to write to potentially blocking ttys safely.  I had a machine
  lock up last night because /dev/console on a serial port got flow control
  blocked.  Setting comcontrol drainwait fixed everything but syslogd which
  was going into a spin trying to write to the console and completely
  ignoreing everything else.
- fix a couple of nonsensical bits of code while here..  eg: wait3 takes
  a pointer to an int.  There is no sense in declaring it as 'union wait',
  then casting the pointer to (int *), then forgetting about it.
This commit is contained in:
peter 1996-11-18 21:48:29 +00:00
parent 064d2d7b63
commit b39cda8f71

View File

@ -39,7 +39,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
*/
static const char rcsid[] =
"$Id: syslogd.c,v 1.10 1996/10/05 15:20:51 peter Exp $";
"$Id: syslogd.c,v 1.12 1996/10/28 08:25:13 joerg Exp $";
#endif /* not lint */
/*
@ -71,7 +71,7 @@ static const char rcsid[] =
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define TTYMSGTIME 1 /* timeout passed to ttymsg */
#define TTYMSGTIME 1 /* timed out passed to ttymsg */
#include <sys/param.h>
#include <sys/ioctl.h>
@ -213,6 +213,7 @@ char *ttymsg __P((struct iovec *, int, char *, int));
void usage __P((void));
void wallmsg __P((struct filed *, struct iovec *));
int waitdaemon __P((int, int, int));
void timedout __P((int));
int
main(argc, argv)
@ -635,6 +636,7 @@ fprintlog(f, flags, msg)
struct iovec *v;
int l;
char line[MAXLINE + 1], repbuf[80], greetings[200];
char *msgret;
v = iov;
if (f->f_type == F_WALL) {
@ -707,40 +709,35 @@ fprintlog(f, flags, msg)
}
/* FALLTHROUGH */
case F_TTY:
case F_FILE:
dprintf(" %s\n", f->f_un.f_fname);
if (f->f_type != F_FILE) {
v->iov_base = "\r\n";
v->iov_len = 2;
} else {
v->iov_base = "\n";
v->iov_len = 1;
}
again:
v->iov_base = "\n";
v->iov_len = 1;
if (writev(f->f_file, iov, 6) < 0) {
int e = errno;
(void)close(f->f_file);
/*
* Check for errors on TTY's due to loss of tty
*/
if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
f->f_file = open(f->f_un.f_fname,
O_WRONLY|O_APPEND, 0);
if (f->f_file < 0) {
f->f_type = F_UNUSED;
logerror(f->f_un.f_fname);
} else
goto again;
} else {
f->f_type = F_UNUSED;
errno = e;
logerror(f->f_un.f_fname);
}
f->f_type = F_UNUSED;
errno = e;
logerror(f->f_un.f_fname);
} else if (flags & SYNC_FILE)
(void)fsync(f->f_file);
break;
case F_TTY:
dprintf(" %s\n", f->f_un.f_fname);
v->iov_base = "\r\n";
v->iov_len = 2;
errno = 0; /* ttymsg() only sometimes returns an errno */
if ((msgret = ttymsg(iov, 6, f->f_un.f_fname, 10))) {
int e = errno;
(void)close(f->f_file);
f->f_type = F_UNUSED;
errno = e;
logerror(msgret);
}
break;
case F_USERS:
case F_WALL:
dprintf("\n");
@ -813,9 +810,9 @@ void
reapchild(signo)
int signo;
{
union wait status;
int status;
while (wait3((int *)&status, WNOHANG, (struct rusage *)NULL) > 0)
while (wait3(&status, WNOHANG, (struct rusage *)NULL) > 0)
;
}
@ -911,7 +908,7 @@ die(signo)
}
if (created_lsock)
(void)unlink(LogName);
exit(0);
exit(1);
}
/*
@ -1227,39 +1224,40 @@ decode(name, codetab)
return (-1);
}
static char *exitmsg;
void
timeout(sig)
int sig __unused;
{
int left;
left = alarm(0);
signal(SIGALRM, SIG_DFL);
if (left == 0)
exitmsg = "timed out waiting for child";
return;
}
/*
* fork off and become a daemon, but wait for the child to come online
* before returing to the parent, or we get disk thrashing at boot etc.
* Set a timer so we don't hang forever if it wedges.
*/
int
waitdaemon(nochdir, noclose, maxwait)
int nochdir, noclose, maxwait;
{
int fd;
int status;
pid_t pid, childpid;
switch (fork()) {
switch (childpid = fork()) {
case -1:
return (-1);
case 0:
break;
default:
signal(SIGALRM, timeout);
signal(SIGALRM, timedout);
alarm(maxwait);
pause();
if (exitmsg)
err(1, exitmsg);
else
exit(0);
while ((pid = wait3(&status, 0, NULL)) != -1) {
if (WIFEXITED(status))
errx(1, "child pid %d exited with return code %d",
pid, WEXITSTATUS(status));
if (WIFSIGNALED(status))
errx(1, "child pid %d exited on signal %d%s",
pid, WTERMSIG(status),
WCOREDUMP(status) ? " (core dumped)" :
"");
if (pid == childpid) /* it's gone... */
break;
}
exit(0);
}
if (setsid() == -1)
@ -1277,3 +1275,23 @@ waitdaemon(nochdir, noclose, maxwait)
}
return (getppid());
}
/*
* We get a SIGALRM from the child when it's running and finished doing it's
* fsync()'s or O_SYNC writes for all the boot messages.
*
* We also get a signal from the kernel if the timer expires, so check to
* see what happened.
*/
void
timedout(sig)
int sig __unused;
{
int left;
left = alarm(0);
signal(SIGALRM, SIG_DFL);
if (left == 0)
errx(1, "timed out waiting for child");
else
exit(0);
}