Browse Source

Make a per-process logger allowing logging to be line buffered yet asynchronous

master
Con Kolivas 10 years ago
parent
commit
fc1d956f37
  1. 52
      src/ckpool.c
  2. 41
      src/ckpool.h

52
src/ckpool.c

@ -34,6 +34,30 @@
ckpool_t *global_ckp; ckpool_t *global_ckp;
static void proclog(ckpool_t *ckp, char *msg)
{
FILE *LOGFP;
int logfd;
if (unlikely(!msg)) {
fprintf(stderr, "Proclog received null message");
return;
}
if (unlikely(!strlen(msg))) {
fprintf(stderr, "Proclog received zero length message");
free(msg);
return;
}
LOGFP = ckp->logfp;
logfd = ckp->logfd;
flock(logfd, LOCK_EX);
fprintf(LOGFP, "%s", msg);
flock(logfd, LOCK_UN);
free(msg);
}
/* Log everything to the logfile, but display warnings on the console as well */ /* Log everything to the logfile, but display warnings on the console as well */
void logmsg(int loglevel, const char *fmt, ...) { void logmsg(int loglevel, const char *fmt, ...) {
if (global_ckp->loglevel >= loglevel && fmt) { if (global_ckp->loglevel >= loglevel && fmt) {
@ -58,14 +82,13 @@ void logmsg(int loglevel, const char *fmt, ...) {
tm->tm_min, tm->tm_min,
tm->tm_sec); tm->tm_sec);
if (logfd) { if (logfd) {
FILE *LOGFP = global_ckp->logfp; char *msg;
flock(logfd, LOCK_EX);
fprintf(LOGFP, "%s %s", stamp, buf);
if (loglevel <= LOG_ERR && errno != 0) if (loglevel <= LOG_ERR && errno != 0)
fprintf(LOGFP, " with errno %d: %s", errno, strerror(errno)); ASPRINTF(&msg, "%s %s with errno %d: %s\n", stamp, buf, errno, strerror(errno));
fprintf(LOGFP, "\n"); else
flock(logfd, LOCK_UN); ASPRINTF(&msg, "%s %s\n", stamp, buf);
ckmsgq_add(global_ckp->logger, msg);
} }
if (loglevel <= LOG_WARNING) {\ if (loglevel <= LOG_WARNING) {\
if (loglevel <= LOG_ERR && errno != 0) if (loglevel <= LOG_ERR && errno != 0)
@ -677,6 +700,17 @@ static void childsighandler(int sig)
kill(ppid, sig); kill(ppid, sig);
} }
static void launch_logger(proc_instance_t *pi)
{
ckpool_t *ckp = pi->ckp;
char loggername[16];
/* Note that the logger is unique per process so it is the only value
* in ckp that differs between processes */
snprintf(loggername, 15, "%clogger", pi->processname[0]);
ckp->logger = create_ckmsgq(ckp, loggername, &proclog);
}
static void launch_process(proc_instance_t *pi) static void launch_process(proc_instance_t *pi)
{ {
pid_t pid; pid_t pid;
@ -688,6 +722,7 @@ static void launch_process(proc_instance_t *pi)
struct sigaction handler; struct sigaction handler;
int ret; int ret;
launch_logger(pi);
handler.sa_handler = &childsighandler; handler.sa_handler = &childsighandler;
handler.sa_flags = 0; handler.sa_flags = 0;
sigemptyset(&handler.sa_mask); sigemptyset(&handler.sa_mask);
@ -1131,13 +1166,16 @@ int main(int argc, char **argv)
ckp.logfp = fopen(buf, "a"); ckp.logfp = fopen(buf, "a");
if (!ckp.logfp) if (!ckp.logfp)
quit(1, "Failed to make open log file %s", buf); quit(1, "Failed to make open log file %s", buf);
ckp.logfd = fileno(ckp.logfp); /* Make logging line buffered */
setvbuf(ckp.logfp, NULL, _IOLBF, 0);
ckp.main.ckp = &ckp; ckp.main.ckp = &ckp;
ckp.main.processname = strdup("main"); ckp.main.processname = strdup("main");
ckp.main.sockname = strdup("listener"); ckp.main.sockname = strdup("listener");
write_namepid(&ckp.main); write_namepid(&ckp.main);
create_process_unixsock(&ckp.main); create_process_unixsock(&ckp.main);
launch_logger(&ckp.main);
ckp.logfd = fileno(ckp.logfp);
create_pthread(&ckp.pth_listener, listener, &ckp.main); create_pthread(&ckp.pth_listener, listener, &ckp.main);

41
src/ckpool.h

@ -20,6 +20,26 @@
struct ckpool_instance; struct ckpool_instance;
typedef struct ckpool_instance ckpool_t; typedef struct ckpool_instance ckpool_t;
struct ckmsg {
struct ckmsg *next;
struct ckmsg *prev;
void *data;
};
typedef struct ckmsg ckmsg_t;
struct ckmsgq {
ckpool_t *ckp;
char name[16];
pthread_t pth;
pthread_mutex_t lock;
pthread_cond_t cond;
ckmsg_t *msgs;
void (*func)(ckpool_t *, void *);
};
typedef struct ckmsgq ckmsgq_t;
struct proc_instance { struct proc_instance {
ckpool_t *ckp; ckpool_t *ckp;
unixsock_t us; unixsock_t us;
@ -81,6 +101,8 @@ struct ckpool_instance {
FILE *logfp; FILE *logfp;
int logfd; int logfd;
/* Logger message queue NOTE: Unique per process */
ckmsgq_t *logger;
/* Process instance data of parent/child processes */ /* Process instance data of parent/child processes */
proc_instance_t main; proc_instance_t main;
@ -129,25 +151,6 @@ struct ckpool_instance {
char **proxypass; char **proxypass;
}; };
struct ckmsg {
struct ckmsg *next;
struct ckmsg *prev;
void *data;
};
typedef struct ckmsg ckmsg_t;
struct ckmsgq {
ckpool_t *ckp;
char name[16];
pthread_t pth;
pthread_mutex_t lock;
pthread_cond_t cond;
ckmsg_t *msgs;
void (*func)(ckpool_t *, void *);
};
typedef struct ckmsgq ckmsgq_t;
ckmsgq_t *create_ckmsgq(ckpool_t *ckp, const char *name, const void *func); ckmsgq_t *create_ckmsgq(ckpool_t *ckp, const char *name, const void *func);
void ckmsgq_add(ckmsgq_t *ckmsgq, void *data); void ckmsgq_add(ckmsgq_t *ckmsgq, void *data);

Loading…
Cancel
Save