Make syslog(3) thread safe.
PR: bin/72394 Submitted by: Dan Nelson Reviewed by: deischen MFC after: 2 weeks
This commit is contained in:
parent
a0ede505d3
commit
9657520621
@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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 const char *LogTag = NULL; /* string to tag the entry with */
|
||||||
static int LogFacility = LOG_USER; /* default facility code */
|
static int LogFacility = LOG_USER; /* default facility code */
|
||||||
static int LogMask = 0xff; /* mask of priorities to be logged */
|
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 disconnectlog(void); /* disconnect from syslogd */
|
||||||
static void connectlog(void); /* (re)connect to syslogd */
|
static void connectlog(void); /* (re)connect to syslogd */
|
||||||
|
static void openlog_unlocked(const char *, int, int);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NOCONN = 0,
|
NOCONN = 0,
|
||||||
@ -134,7 +146,7 @@ vsyslog(pri, fmt, ap)
|
|||||||
char ch, *p;
|
char ch, *p;
|
||||||
time_t now;
|
time_t now;
|
||||||
int fd, saved_errno;
|
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;
|
FILE *fp, *fmt_fp;
|
||||||
struct bufcookie tbuf_cookie;
|
struct bufcookie tbuf_cookie;
|
||||||
struct bufcookie fmt_cookie;
|
struct bufcookie fmt_cookie;
|
||||||
@ -147,9 +159,13 @@ vsyslog(pri, fmt, ap)
|
|||||||
pri &= LOG_PRIMASK|LOG_FACMASK;
|
pri &= LOG_PRIMASK|LOG_FACMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
THREAD_LOCK();
|
||||||
|
|
||||||
/* Check priority against setlogmask values. */
|
/* Check priority against setlogmask values. */
|
||||||
if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
|
if (!(LOG_MASK(LOG_PRI(pri)) & LogMask)) {
|
||||||
|
THREAD_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
@ -161,8 +177,10 @@ vsyslog(pri, fmt, ap)
|
|||||||
tbuf_cookie.base = tbuf;
|
tbuf_cookie.base = tbuf;
|
||||||
tbuf_cookie.left = sizeof(tbuf);
|
tbuf_cookie.left = sizeof(tbuf);
|
||||||
fp = fwopen(&tbuf_cookie, writehook);
|
fp = fwopen(&tbuf_cookie, writehook);
|
||||||
if (fp == NULL)
|
if (fp == NULL) {
|
||||||
|
THREAD_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Build the message. */
|
/* Build the message. */
|
||||||
(void)time(&now);
|
(void)time(&now);
|
||||||
@ -192,6 +210,7 @@ vsyslog(pri, fmt, ap)
|
|||||||
fmt_fp = fwopen(&fmt_cookie, writehook);
|
fmt_fp = fwopen(&fmt_cookie, writehook);
|
||||||
if (fmt_fp == NULL) {
|
if (fmt_fp == NULL) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
THREAD_UNLOCK();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +222,8 @@ vsyslog(pri, fmt, ap)
|
|||||||
for ( ; (ch = *fmt); ++fmt) {
|
for ( ; (ch = *fmt); ++fmt) {
|
||||||
if (ch == '%' && fmt[1] == 'm') {
|
if (ch == '%' && fmt[1] == 'm') {
|
||||||
++fmt;
|
++fmt;
|
||||||
fputs(strerror(saved_errno), fmt_fp);
|
strerror_r(saved_errno, errstr, sizeof(errstr));
|
||||||
|
fputs(errstr, fmt_fp);
|
||||||
} else if (ch == '%' && fmt[1] == '%') {
|
} else if (ch == '%' && fmt[1] == '%') {
|
||||||
++fmt;
|
++fmt;
|
||||||
fputc(ch, fmt_fp);
|
fputc(ch, fmt_fp);
|
||||||
@ -247,7 +267,7 @@ vsyslog(pri, fmt, ap)
|
|||||||
|
|
||||||
/* Get connected, output the message to the local logger. */
|
/* Get connected, output the message to the local logger. */
|
||||||
if (!opened)
|
if (!opened)
|
||||||
openlog(LogTag, LogStat | LOG_NDELAY, 0);
|
openlog_unlocked(LogTag, LogStat | LOG_NDELAY, 0);
|
||||||
connectlog();
|
connectlog();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -272,13 +292,17 @@ vsyslog(pri, fmt, ap)
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
usleep(1);
|
usleep(1);
|
||||||
if (send(LogFile, tbuf, cnt, 0) >= 0)
|
if (send(LogFile, tbuf, cnt, 0) >= 0) {
|
||||||
|
THREAD_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (status == CONNPRIV)
|
if (status == CONNPRIV)
|
||||||
break;
|
break;
|
||||||
} while (errno == ENOBUFS);
|
} while (errno == ENOBUFS);
|
||||||
} else
|
} else {
|
||||||
|
THREAD_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output the message to the console; try not to block
|
* Output the message to the console; try not to block
|
||||||
@ -299,7 +323,11 @@ vsyslog(pri, fmt, ap)
|
|||||||
(void)_writev(fd, iov, 2);
|
(void)_writev(fd, iov, 2);
|
||||||
(void)_close(fd);
|
(void)_close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
THREAD_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should be called with mutex acquired */
|
||||||
static void
|
static void
|
||||||
disconnectlog()
|
disconnectlog()
|
||||||
{
|
{
|
||||||
@ -315,6 +343,7 @@ disconnectlog()
|
|||||||
status = NOCONN; /* retry connect */
|
status = NOCONN; /* retry connect */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should be called with mutex acquired */
|
||||||
static void
|
static void
|
||||||
connectlog()
|
connectlog()
|
||||||
{
|
{
|
||||||
@ -366,8 +395,8 @@ connectlog()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
openlog(ident, logstat, logfac)
|
openlog_unlocked(ident, logstat, logfac)
|
||||||
const char *ident;
|
const char *ident;
|
||||||
int logstat, logfac;
|
int logstat, logfac;
|
||||||
{
|
{
|
||||||
@ -383,13 +412,26 @@ openlog(ident, logstat, logfac)
|
|||||||
opened = 1; /* ident and facility has been set */
|
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
|
void
|
||||||
closelog()
|
closelog()
|
||||||
{
|
{
|
||||||
|
THREAD_LOCK();
|
||||||
(void)_close(LogFile);
|
(void)_close(LogFile);
|
||||||
LogFile = -1;
|
LogFile = -1;
|
||||||
LogTag = NULL;
|
LogTag = NULL;
|
||||||
status = NOCONN;
|
status = NOCONN;
|
||||||
|
THREAD_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setlogmask -- set the log mask level */
|
/* setlogmask -- set the log mask level */
|
||||||
@ -399,8 +441,10 @@ setlogmask(pmask)
|
|||||||
{
|
{
|
||||||
int omask;
|
int omask;
|
||||||
|
|
||||||
|
THREAD_LOCK();
|
||||||
omask = LogMask;
|
omask = LogMask;
|
||||||
if (pmask != 0)
|
if (pmask != 0)
|
||||||
LogMask = pmask;
|
LogMask = pmask;
|
||||||
|
THREAD_UNLOCK();
|
||||||
return (omask);
|
return (omask);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user