diff --git a/server.c b/server.c index 081c1e9..ae0e823 100644 --- a/server.c +++ b/server.c @@ -77,7 +77,6 @@ server_new(const char *cfg_file) { struct server *s = calloc(1, sizeof(struct server)); s->cfg = conf_read(cfg_file); - pthread_spin_init(&s->log_lock, PTHREAD_PROCESS_SHARED); /* workers */ s->w = calloc(s->cfg->http_threads, sizeof(struct worker*)); @@ -155,6 +154,8 @@ server_start(struct server *s) { signal(SIGPIPE, SIG_IGN); #endif + slog_init(s); + /* start worker threads */ for(i = 0; i < s->cfg->http_threads; ++i) { worker_start(s->w[i]); diff --git a/server.h b/server.h index 4c85e64..42438b3 100644 --- a/server.h +++ b/server.h @@ -21,7 +21,10 @@ struct server { int next_worker; /* log lock */ - pthread_spinlock_t log_lock; + struct { + pid_t self; + int fd; + } log; }; struct server * diff --git a/slog.c b/slog.c index 5722b35..73a68d3 100644 --- a/slog.c +++ b/slog.c @@ -5,42 +5,63 @@ #include #include #include -#include #include +#include +#include #include "slog.h" #include "server.h" #include "conf.h" +/** + * Initialize log writer. + */ +void +slog_init(struct server *s) { + + s->log.self = getpid(); + + if(s->cfg->logfile) { + s->log.fd = open(s->cfg->logfile, + O_WRONLY | O_APPEND | O_CREAT, S_IRUSR|S_IWUSR); + } else { + s->log.fd = 2; /* stderr */ + } +} + +/** + * Write log message to disk, or stderr. + */ void slog(struct server *s, log_level level, const char *body, size_t sz) { const char *c = ".-*#"; - time_t now = time(NULL); - static FILE *fp = NULL; - char buf[64]; + time_t now; + char time_buf[64]; char msg[124]; - - - static pid_t self = 0; - if(!self) self = getpid(); + char line[256]; /* bounds are checked. */ + int line_sz, ret; if(level > s->cfg->verbosity) return; /* too verbose */ - pthread_spin_lock(&s->log_lock); - - if(!fp) fp = (s->cfg->logfile == NULL) ? stdout : fopen(s->cfg->logfile, "a"); - if(!fp) goto end; + if(!s->log.fd) return; /* limit message size */ sz = sz ? sz:strlen(body); snprintf(msg, sz + 1 > sizeof(msg) ? sizeof(msg) : sz + 1, "%s", body); - strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now)); - fprintf(fp,"[%d] %s %c %s\n", (int)self, buf, c[level], msg); - fflush(fp); + /* get current time */ + now = time(NULL); + strftime(time_buf, sizeof(time_buf), "%d %b %H:%M:%S", localtime(&now)); + + /* generate output line. */ + line_sz = snprintf(line, sizeof(line), + "[%d] %s %d %s\n", (int)s->log.self, time_buf, c[level], msg); + + /* write to log and flush to disk. */ + ret = write(s->log.fd, line, line_sz); + ret = fsync(s->log.fd); -end: - pthread_spin_unlock(&s->log_lock); + (void)ret; } diff --git a/slog.h b/slog.h index ae61bd3..b44804c 100644 --- a/slog.h +++ b/slog.h @@ -11,6 +11,9 @@ typedef enum { struct server; +void +slog_init(struct server *s); + void slog(struct server *s, log_level level, const char *body, size_t sz);