Make syslog(3) thread safe.

PR:		bin/72394
Submitted by:	Dan Nelson
Reviewed by:	deischen
MFC after:	2 weeks
This commit is contained in:
Gleb Smirnoff 2004-12-30 16:05:11 +00:00
parent a0ede505d3
commit 9657520621

View File

@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -66,9 +67,20 @@ static int LogStat = 0; /* status bits, set by openlog() */
static const char *LogTag = NULL; /* string to tag the entry with */
static int LogFacility = LOG_USER; /* default facility code */
static int LogMask = 0xff; /* mask of priorities to be logged */
static pthread_mutex_t syslog_mutex = PTHREAD_MUTEX_INITIALIZER;
#define THREAD_LOCK() \
do { \
if (__isthreaded) _pthread_mutex_lock(&syslog_mutex); \
} while(0)
#define THREAD_UNLOCK() \
do { \
if (__isthreaded) _pthread_mutex_unlock(&syslog_mutex); \
} while(0)
static void disconnectlog(void); /* disconnect from syslogd */
static void connectlog(void); /* (re)connect to syslogd */
static void openlog_unlocked(const char *, int, int);
enum {
NOCONN = 0,
@ -134,7 +146,7 @@ vsyslog(pri, fmt, ap)
char ch, *p;
time_t now;
int fd, saved_errno;
char *stdp, tbuf[2048], fmt_cpy[1024], timbuf[26];
char *stdp, tbuf[2048], fmt_cpy[1024], timbuf[26], errstr[64];
FILE *fp, *fmt_fp;
struct bufcookie tbuf_cookie;
struct bufcookie fmt_cookie;
@ -147,9 +159,13 @@ vsyslog(pri, fmt, ap)
pri &= LOG_PRIMASK|LOG_FACMASK;
}
THREAD_LOCK();
/* Check priority against setlogmask values. */
if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
if (!(LOG_MASK(LOG_PRI(pri)) & LogMask)) {
THREAD_UNLOCK();
return;
}
saved_errno = errno;
@ -161,8 +177,10 @@ vsyslog(pri, fmt, ap)
tbuf_cookie.base = tbuf;
tbuf_cookie.left = sizeof(tbuf);
fp = fwopen(&tbuf_cookie, writehook);
if (fp == NULL)
if (fp == NULL) {
THREAD_UNLOCK();
return;
}
/* Build the message. */
(void)time(&now);
@ -192,6 +210,7 @@ vsyslog(pri, fmt, ap)
fmt_fp = fwopen(&fmt_cookie, writehook);
if (fmt_fp == NULL) {
fclose(fp);
THREAD_UNLOCK();
return;
}
@ -203,7 +222,8 @@ vsyslog(pri, fmt, ap)
for ( ; (ch = *fmt); ++fmt) {
if (ch == '%' && fmt[1] == 'm') {
++fmt;
fputs(strerror(saved_errno), fmt_fp);
strerror_r(saved_errno, errstr, sizeof(errstr));
fputs(errstr, fmt_fp);
} else if (ch == '%' && fmt[1] == '%') {
++fmt;
fputc(ch, fmt_fp);
@ -247,7 +267,7 @@ vsyslog(pri, fmt, ap)
/* Get connected, output the message to the local logger. */
if (!opened)
openlog(LogTag, LogStat | LOG_NDELAY, 0);
openlog_unlocked(LogTag, LogStat | LOG_NDELAY, 0);
connectlog();
/*
@ -272,13 +292,17 @@ vsyslog(pri, fmt, ap)
}
do {
usleep(1);
if (send(LogFile, tbuf, cnt, 0) >= 0)
if (send(LogFile, tbuf, cnt, 0) >= 0) {
THREAD_UNLOCK();
return;
}
if (status == CONNPRIV)
break;
} while (errno == ENOBUFS);
} else
} else {
THREAD_UNLOCK();
return;
}
/*
* Output the message to the console; try not to block
@ -299,7 +323,11 @@ vsyslog(pri, fmt, ap)
(void)_writev(fd, iov, 2);
(void)_close(fd);
}
THREAD_UNLOCK();
}
/* Should be called with mutex acquired */
static void
disconnectlog()
{
@ -315,6 +343,7 @@ disconnectlog()
status = NOCONN; /* retry connect */
}
/* Should be called with mutex acquired */
static void
connectlog()
{
@ -366,8 +395,8 @@ connectlog()
}
}
void
openlog(ident, logstat, logfac)
static void
openlog_unlocked(ident, logstat, logfac)
const char *ident;
int logstat, logfac;
{
@ -383,13 +412,26 @@ openlog(ident, logstat, logfac)
opened = 1; /* ident and facility has been set */
}
void
openlog(ident, logstat, logfac)
const char *ident;
int logstat, logfac;
{
THREAD_LOCK();
openlog_unlocked(ident, logstat, logfac);
THREAD_UNLOCK();
}
void
closelog()
{
THREAD_LOCK();
(void)_close(LogFile);
LogFile = -1;
LogTag = NULL;
status = NOCONN;
THREAD_UNLOCK();
}
/* setlogmask -- set the log mask level */
@ -399,8 +441,10 @@ setlogmask(pmask)
{
int omask;
THREAD_LOCK();
omask = LogMask;
if (pmask != 0)
LogMask = pmask;
THREAD_UNLOCK();
return (omask);
}