When send()ing to syslogd return ENOBUFS keep trying until success.

This fixes a case, when DoSed syslogd completely loses messages.

PR:		bin/72366
Discussed with:	dwmalone, millert@OpenBSD.org
Approved by:	julian (mentor)
Obtained from:	OpenBSD (rev. 1.17, 1.21 by millert)
MFC after:	3 months
This commit is contained in:
Gleb Smirnoff 2004-10-08 21:15:21 +00:00
parent a7721a3695
commit 2e89951b6f

View File

@ -243,17 +243,27 @@ vsyslog(pri, fmt, ap)
if (!opened)
openlog(LogTag, LogStat | LOG_NDELAY, 0);
connectlog();
if (send(LogFile, tbuf, cnt, 0) >= 0)
return;
/*
* If the send() failed, the odds are syslogd was restarted.
* Make one (only) attempt to reconnect to /dev/log.
* If the send() failed, there are two likely scenarios:
* 1) syslogd was restarted
* 2) /var/run/log is out of socket buffer space
* We attempt to reconnect to /var/run/log to take care of
* case #1 and keep send()ing data to cover case #2
* to give syslogd a chance to empty its socket buffer.
*/
disconnectlog();
connectlog();
if (send(LogFile, tbuf, cnt, 0) >= 0)
return;
if (send(LogFile, tbuf, cnt, 0) < 0) {
if (errno != ENOBUFS) {
disconnectlog();
connectlog();
}
do {
usleep(1);
if (send(LogFile, tbuf, cnt, 0) >= 0)
break;
} while (errno == ENOBUFS);
}
/*
* Output the message to the console; try not to block