Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Use a serial dispatch queue for logging

  • Loading branch information...
commit 7ea148fc54285d993d178289ab4fe35ceb37b2df 1 parent 42b501b
Julien BLACHE authored
Showing with 149 additions and 23 deletions.
  1. +5 −1 forked-daapd.8
  2. +120 −21 src/logger.c
  3. +3 −0  src/logger.h
  4. +21 −1 src/main.c
View
6 forked-daapd.8
@@ -1,5 +1,5 @@
.\" -*- nroff -*-
-.TH FORKED-DAAPD "8" "2010-01-05" "forked-daapd" "RSP & DAAP media server"
+.TH FORKED-DAAPD "8" "2010-07-18" "forked-daapd" "RSP & DAAP media server"
.SH NAME
mt\-daapd \- RSP & iTunes\-compatible DAAP server
.SH SYNOPSIS
@@ -21,6 +21,10 @@ Debug domains; available domains are: \fIconfig\fP, \fIdaap\fP,
\fIdb\fP, \fIhttpd\fP, \fImain\fP, \fImdns\fP, \fImisc\fP,
\fIrsp\fP, \fIscan\fP, \fIxcode\fP, \fIevent\fP.
.TP
+\fB\-s\fR
+Synchronous logging; logging is asynchronous by default. Use when
+debugging, especially if debugging a crash.
+.TP
\fB\-c\fR \fIfile\fP
Use \fIfile\fP as the configuration file.
.TP
View
141 src/logger.c
@@ -27,8 +27,8 @@
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
-#include <pthread.h>
+#include <dispatch/dispatch.h>
#include <event.h>
#include <libavutil/log.h>
@@ -37,7 +37,8 @@
#include "logger.h"
-static pthread_mutex_t logger_lck = PTHREAD_MUTEX_INITIALIZER;
+static dispatch_queue_t logger_sq;
+static int logsync;
static int logdomains;
static int threshold;
static int console;
@@ -82,21 +83,85 @@ static void
vlogger(int severity, int domain, const char *fmt, va_list args)
{
va_list ap;
- char stamp[32];
+ char *msg;
time_t t;
int ret;
+ dispatch_block_t logblock;
if (!((1 << domain) & logdomains) || (severity > threshold))
return;
- pthread_mutex_lock(&logger_lck);
+ t = time(NULL);
- if (!logfile && !console)
+ va_copy(ap, args);
+ ret = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ if (ret <= 0)
+ return;
+
+ msg = (char *)malloc(ret + 1);
+ if (!msg)
+ return;
+
+ va_copy(ap, args);
+ ret = vsnprintf(msg, ret + 1, fmt, ap);
+ va_end(ap);
+
+ if (ret < 0)
{
- pthread_mutex_unlock(&logger_lck);
+ free(msg);
return;
}
+
+ logblock = ^{
+ char stamp[32];
+ int ret;
+
+ if (!logfile && !console)
+ {
+ free(msg);
+ return;
+ }
+
+ if (logfile)
+ {
+ ret = strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&t));
+ if (ret == 0)
+ stamp[0] = '\0';
+
+ fprintf(logfile, "[%s] %8s: %s", stamp, labels[domain], msg);
+
+ fflush(logfile);
+ }
+
+ if (console)
+ fprintf(stderr, "%8s: %s", labels[domain], msg);
+
+ free(msg);
+ };
+
+ if (logsync)
+ dispatch_sync(logger_sq, logblock);
+ else
+ dispatch_async(logger_sq, logblock);
+}
+
+static void
+vlogger_early(int severity, int domain, const char *fmt, va_list args)
+{
+ va_list ap;
+ char stamp[32];
+ time_t t;
+ int ret;
+
+ if (!((1 << domain) & logdomains) || (severity > threshold))
+ return;
+
+ if (!logfile && !console)
+ return;
+
if (logfile)
{
t = time(NULL);
@@ -121,8 +186,6 @@ vlogger(int severity, int domain, const char *fmt, va_list args)
vfprintf(stderr, fmt, ap);
va_end(ap);
}
-
- pthread_mutex_unlock(&logger_lck);
}
void
@@ -131,7 +194,12 @@ DPRINTF(int severity, int domain, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- vlogger(severity, domain, fmt, ap);
+
+ if (!logger_sq)
+ vlogger_early(severity, domain, fmt, ap);
+ else
+ vlogger(severity, domain, fmt, ap);
+
va_end(ap);
}
@@ -196,33 +264,37 @@ logger_alsa(const char *file, int line, const char *function, int err, const cha
}
#endif /* LAUDIO_USE_ALSA */
-void
-logger_reinit(void)
+/* Queue: logger_sq */
+static void
+logger_reinit_task(void *arg)
{
FILE *fp;
if (!logfile)
return;
- pthread_mutex_lock(&logger_lck);
-
fp = fopen(logfilename, "a");
if (!fp)
{
- fprintf(logfile, "Could not reopen logfile: %s\n", strerror(errno));
-
- goto out;
+ DPRINTF(E_LOG, L_MAIN, "Could not reopen logfile: %s\n", strerror(errno));
+ return;
}
fclose(logfile);
logfile = fp;
+}
+
+void
+logger_reinit(void)
+{
+ if (!logger_sq)
+ return;
- out:
- pthread_mutex_unlock(&logger_lck);
+ dispatch_sync_f(logger_sq, NULL, logger_reinit_task);
}
-/* The functions below are used at init time with a single thread running */
+/* The functions below are used at init time before switching to dispatch mode */
void
logger_domains(void)
{
@@ -243,6 +315,18 @@ logger_detach(void)
}
int
+logger_start_dispatch(int sync)
+{
+ logger_sq = dispatch_queue_create("org.forked-daapd.logger", NULL);
+ if (!logger_sq)
+ return -1;
+
+ logsync = sync;
+
+ return 0;
+}
+
+int
logger_init(char *file, char *domains, int severity)
{
int ret;
@@ -254,6 +338,7 @@ logger_init(char *file, char *domains, int severity)
return -1;
}
+ logger_sq = NULL;
console = 1;
threshold = severity;
@@ -293,6 +378,20 @@ logger_init(char *file, char *domains, int severity)
void
logger_deinit(void)
{
- if (logfile)
- fclose(logfile);
+ if (logger_sq)
+ {
+ dispatch_sync(logger_sq,
+ ^{
+ if (logfile)
+ fclose(logfile);
+ });
+
+ dispatch_release(logger_sq);
+ logger_sq = NULL;
+ }
+ else
+ {
+ if (logfile)
+ fclose(logfile);
+ }
}
View
3  src/logger.h
@@ -62,6 +62,9 @@ void
logger_detach(void);
int
+logger_start_dispatch(int sync);
+
+int
logger_init(char *file, char *domains, int severity);
void
View
22 src/main.c
@@ -440,6 +440,7 @@ main(int argc, char **argv)
int mdns_no_rsp;
int mdns_no_daap;
int loglevel;
+ int logsync;
char *logdomains;
char *logfile;
char *ffid;
@@ -456,6 +457,7 @@ main(int argc, char **argv)
{
{ "ffid", 1, NULL, 'b' },
{ "debug", 1, NULL, 'd' },
+ { "synclog", 0, NULL, 's' },
{ "logdomains", 1, NULL, 'D' },
{ "foreground", 0, NULL, 'f' },
{ "config", 1, NULL, 'c' },
@@ -471,6 +473,7 @@ main(int argc, char **argv)
configfile = CONFFILE;
pidfile = PIDFILE;
loglevel = -1;
+ logsync = 0;
logdomains = NULL;
logfile = NULL;
background = 1;
@@ -478,7 +481,7 @@ main(int argc, char **argv)
mdns_no_rsp = 0;
mdns_no_daap = 0;
- while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1)
+ while ((option = getopt_long(argc, argv, "D:d:sc:P:fb:v", option_map, NULL)) != -1)
{
switch (option)
{
@@ -506,6 +509,10 @@ main(int argc, char **argv)
logdomains = optarg;
break;
+ case 's':
+ logsync = 1;
+ break;
+
case 'f':
background = 0;
break;
@@ -634,6 +641,18 @@ main(int argc, char **argv)
goto daemon_fail;
}
+ /* Switch logger into dispatch mode (after forking) */
+ ret = logger_start_dispatch(logsync);
+ if (ret < 0)
+ {
+ DPRINTF(E_FATAL, L_MAIN, "Could not switch logger to dispatch mode\n");
+
+ ret = EXIT_FAILURE;
+ goto logger_dispatch_fail;
+ }
+
+ DPRINTF(E_DBG, L_MAIN, "Logger switched to dispatch mode\n");
+
/* Initialize libevent (after forking) */
evbase_main = event_init();
@@ -801,6 +820,7 @@ main(int argc, char **argv)
}
mdns_fail:
+ logger_dispatch_fail:
daemon_fail:
if (background)
{
Please sign in to comment.
Something went wrong with that request. Please try again.