[core] support multiple error logs
e.g. different server.errorlog for different virtual hosts Also, support different server.breakagelog to have separate script error logs, applicable to mod_cgi and mod_ssi exec.personal/stbuehler/ci-build
parent
19985261b2
commit
fda01e3305
10
src/base.h
10
src/base.h
|
@ -81,9 +81,6 @@ typedef struct {
|
|||
const buffer *document_root;
|
||||
const buffer *server_name;
|
||||
const buffer *server_tag;
|
||||
const buffer *error_handler;
|
||||
const buffer *error_handler_404;
|
||||
const buffer *errorfile_prefix;
|
||||
log_error_st *errh;
|
||||
|
||||
unsigned short max_keep_alive_requests;
|
||||
|
@ -130,6 +127,11 @@ typedef struct {
|
|||
*
|
||||
*/
|
||||
off_t *global_bytes_per_second_cnt_ptr; /* */
|
||||
|
||||
const buffer *error_handler;
|
||||
const buffer *error_handler_404;
|
||||
const buffer *errorfile_prefix;
|
||||
log_error_st *serrh; /* script errh */
|
||||
} specific_config;
|
||||
|
||||
/* the order of the items should be the same as they are processed
|
||||
|
@ -276,8 +278,6 @@ typedef struct {
|
|||
unsigned char config_unsupported;
|
||||
unsigned char systemd_socket_activation;
|
||||
unsigned char errorlog_use_syslog;
|
||||
const buffer *errorlog_file;
|
||||
const buffer *breakagelog_file;
|
||||
const buffer *syslog_facility;
|
||||
const buffer *bindhost;
|
||||
const buffer *changeroot;
|
||||
|
|
344
src/configfile.c
344
src/configfile.c
|
@ -25,6 +25,10 @@
|
|||
#include <limits.h>
|
||||
#include <glob.h>
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
@ -175,6 +179,12 @@ static void config_merge_config_cpv(specific_config * const pconf, const config_
|
|||
case 30:/* debug.log-timeouts */
|
||||
pconf->log_timeouts = (0 != cpv->v.u);
|
||||
break;
|
||||
case 31: /* server.errorlog */
|
||||
if (cpv->vtype == T_CONFIG_LOCAL) pconf->errh = cpv->v.v;
|
||||
break;
|
||||
case 32:/* server.breakagelog */
|
||||
if (cpv->vtype == T_CONFIG_LOCAL) pconf->serrh = cpv->v.v;
|
||||
break;
|
||||
default:/* should not happen */
|
||||
return;
|
||||
}
|
||||
|
@ -507,10 +517,10 @@ static int config_insert_srvconf(server *srv) {
|
|||
,{ CONST_STR_LEN("server.groupname"),
|
||||
T_CONFIG_STRING,
|
||||
T_CONFIG_SCOPE_SERVER }
|
||||
,{ CONST_STR_LEN("server.errorlog"),
|
||||
,{ CONST_STR_LEN("server.errorlog-placeholder-moved-to-config-insert"),
|
||||
T_CONFIG_STRING,
|
||||
T_CONFIG_SCOPE_SERVER }
|
||||
,{ CONST_STR_LEN("server.breakagelog"),
|
||||
,{ CONST_STR_LEN("server.breakagelog-placeholder-moved-to-config-insert"),
|
||||
T_CONFIG_STRING,
|
||||
T_CONFIG_SCOPE_SERVER }
|
||||
,{ CONST_STR_LEN("server.errorlog-use-syslog"),
|
||||
|
@ -625,11 +635,11 @@ static int config_insert_srvconf(server *srv) {
|
|||
case 8: /* server.groupname */
|
||||
srv->srvconf.groupname = cpv->v.b;
|
||||
break;
|
||||
case 9: /* server.errorlog */
|
||||
srv->srvconf.errorlog_file = cpv->v.b;
|
||||
case 9: /* server.errorlog */ /* moved to config_insert() */
|
||||
/*srv->srvconf.errorlog_file = cpv->v.b;*/
|
||||
break;
|
||||
case 10:/* server.breakagelog */
|
||||
srv->srvconf.breakagelog_file = cpv->v.b;
|
||||
case 10:/* server.breakagelog */ /* moved to config_insert() */
|
||||
/*srv->srvconf.breakagelog_file = cpv->v.b;*/
|
||||
break;
|
||||
case 11:/* server.errorlog-use-syslog */
|
||||
srv->srvconf.errorlog_use_syslog = (unsigned short)cpv->v.u;
|
||||
|
@ -821,6 +831,12 @@ static int config_insert(server *srv) {
|
|||
,{ CONST_STR_LEN("debug.log-timeouts"),
|
||||
T_CONFIG_BOOL,
|
||||
T_CONFIG_SCOPE_CONNECTION }
|
||||
,{ CONST_STR_LEN("server.errorlog"),
|
||||
T_CONFIG_STRING,
|
||||
T_CONFIG_SCOPE_CONNECTION }
|
||||
,{ CONST_STR_LEN("server.breakagelog"),
|
||||
T_CONFIG_STRING,
|
||||
T_CONFIG_SCOPE_CONNECTION }
|
||||
,{ NULL, 0,
|
||||
T_CONFIG_UNSET,
|
||||
T_CONFIG_SCOPE_UNSET }
|
||||
|
@ -914,6 +930,8 @@ static int config_insert(server *srv) {
|
|||
case 28:/* debug.log-request-header */
|
||||
case 29:/* debug.log-response-header */
|
||||
case 30:/* debug.log-timeouts */
|
||||
case 31:/* server.errorlog */ /*(idx in server.c must match)*/
|
||||
case 32:/* server.breakagelog *//*(idx in server.c must match)*/
|
||||
break;
|
||||
default:/* should not happen */
|
||||
break;
|
||||
|
@ -1049,6 +1067,320 @@ void config_init(server *srv) {
|
|||
srv->srvconf.upload_tempdirs = array_init(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* open the errorlog
|
||||
*
|
||||
* we have 4 possibilities:
|
||||
* - stderr (default)
|
||||
* - syslog
|
||||
* - logfile
|
||||
* - pipe
|
||||
*
|
||||
*/
|
||||
|
||||
static void config_log_error_open_syslog(server *srv, log_error_st *errh, const buffer *syslog_facility) {
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
errh->errorlog_mode = ERRORLOG_SYSLOG;
|
||||
/* perhaps someone wants to use syslog() */
|
||||
int facility = -1;
|
||||
if (!buffer_string_is_empty(syslog_facility)) {
|
||||
static const struct facility_name_st {
|
||||
const char *name;
|
||||
int val;
|
||||
} facility_names[] = {
|
||||
{ "auth", LOG_AUTH }
|
||||
#ifdef LOG_AUTHPRIV
|
||||
,{ "authpriv", LOG_AUTHPRIV }
|
||||
#endif
|
||||
#ifdef LOG_CRON
|
||||
,{ "cron", LOG_CRON }
|
||||
#endif
|
||||
,{ "daemon", LOG_DAEMON }
|
||||
#ifdef LOG_FTP
|
||||
,{ "ftp", LOG_FTP }
|
||||
#endif
|
||||
#ifdef LOG_KERN
|
||||
,{ "kern", LOG_KERN }
|
||||
#endif
|
||||
#ifdef LOG_LPR
|
||||
,{ "lpr", LOG_LPR }
|
||||
#endif
|
||||
#ifdef LOG_MAIL
|
||||
,{ "mail", LOG_MAIL }
|
||||
#endif
|
||||
#ifdef LOG_NEWS
|
||||
,{ "news", LOG_NEWS }
|
||||
#endif
|
||||
,{ "security", LOG_AUTH } /* DEPRECATED */
|
||||
#ifdef LOG_SYSLOG
|
||||
,{ "syslog", LOG_SYSLOG }
|
||||
#endif
|
||||
#ifdef LOG_USER
|
||||
,{ "user", LOG_USER }
|
||||
#endif
|
||||
#ifdef LOG_UUCP
|
||||
,{ "uucp", LOG_UUCP }
|
||||
#endif
|
||||
,{ "local0", LOG_LOCAL0 }
|
||||
,{ "local1", LOG_LOCAL1 }
|
||||
,{ "local2", LOG_LOCAL2 }
|
||||
,{ "local3", LOG_LOCAL3 }
|
||||
,{ "local4", LOG_LOCAL4 }
|
||||
,{ "local5", LOG_LOCAL5 }
|
||||
,{ "local6", LOG_LOCAL6 }
|
||||
,{ "local7", LOG_LOCAL7 }
|
||||
};
|
||||
for (unsigned int i = 0; i < sizeof(facility_names)/sizeof(facility_names[0]); ++i) {
|
||||
const struct facility_name_st *f = facility_names+i;
|
||||
if (0 == strcmp(syslog_facility->ptr, f->name)) {
|
||||
facility = f->val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == facility) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"unrecognized server.syslog-facility: \"%s\"; "
|
||||
"defaulting to \"daemon\" facility",
|
||||
syslog_facility->ptr);
|
||||
}
|
||||
}
|
||||
openlog("lighttpd", LOG_CONS|LOG_PID, -1==facility ? LOG_DAEMON : facility);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int config_log_error_open_fn(server *srv, log_error_st *errh, const char *fn) {
|
||||
int fd = fdevent_open_logger(fn);
|
||||
if (-1 == fd) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"opening errorlog '%s' failed", fn);
|
||||
return -1;
|
||||
}
|
||||
errh->errorlog_fd = fd;
|
||||
errh->errorlog_mode = fn[0] == '|' ? ERRORLOG_PIPE : ERRORLOG_FILE;
|
||||
errh->fn = fn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_log_error_open(server *srv) {
|
||||
/* logs are opened after preflight check (srv->srvconf.preflight_check)
|
||||
* and after dropping privileges instead of being opened during config
|
||||
* processing */
|
||||
|
||||
/* Note: implementation does not de-dup repeated files or pipe commands */
|
||||
|
||||
config_data_base * const p = srv->config_data_base;
|
||||
log_error_st *serrh = NULL;
|
||||
|
||||
/* future: might be slightly faster to have allocated array of open files
|
||||
* rather than walking config, but only might matter with many directives */
|
||||
/* (init i to 0 if global context; to 1 to skip empty global context) */
|
||||
for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
|
||||
config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
for (; -1 != cpv->k_id; ++cpv) {
|
||||
const char *fn = NULL;
|
||||
log_error_st *errh = NULL;
|
||||
switch (cpv->k_id) {
|
||||
/* NB: these indexes are repeated below switch() block
|
||||
* and all must stay in sync with configfile.c */
|
||||
case 31:/* server.errorlog */
|
||||
if (0 == i) {
|
||||
if (srv->srvconf.errorlog_use_syslog) continue;
|
||||
errh = srv->errh;
|
||||
}
|
||||
__attribute_fallthrough__
|
||||
case 32:/* server.breakagelog */
|
||||
if (!buffer_string_is_empty(cpv->v.b)) fn = cpv->v.b->ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == fn) continue;
|
||||
|
||||
if (NULL == errh) errh = log_error_st_init();
|
||||
cpv->v.v = errh;
|
||||
cpv->vtype = T_CONFIG_LOCAL;
|
||||
|
||||
if (0 != config_log_error_open_fn(srv, errh, fn)) return -1;
|
||||
|
||||
if (0 == i && errh != srv->errh) /*(top-level server.breakagelog)*/
|
||||
serrh = errh;
|
||||
}
|
||||
}
|
||||
|
||||
if (srv->srvconf.errorlog_use_syslog) /*(restricted to global scope)*/
|
||||
config_log_error_open_syslog(srv, srv->errh,
|
||||
srv->srvconf.syslog_facility);
|
||||
else if (srv->errh->errorlog_mode == ERRORLOG_FD
|
||||
&& !srv->srvconf.dont_daemonize)
|
||||
srv->errh->errorlog_fd = -1;
|
||||
/* We can only log to stderr in dont-daemonize mode;
|
||||
* if we do daemonize and no errorlog file is specified,
|
||||
* we log into /dev/null
|
||||
*/
|
||||
|
||||
/* Note: serrh should not be stored in p->defaults.serrh
|
||||
* If left as NULL, scripts (e.g. mod_cgi and mod_ssi exec) will inherit
|
||||
* the current STDERR_FILENO, which already is the top-level breakagelog. */
|
||||
/*p->defaults.serrh = serrh;*/
|
||||
|
||||
int errfd;
|
||||
if (NULL != serrh) {
|
||||
if (srv->errh->errorlog_mode == ERRORLOG_FD) {
|
||||
srv->errh->errorlog_fd = dup(STDERR_FILENO);
|
||||
fdevent_setfd_cloexec(srv->errh->errorlog_fd);
|
||||
}
|
||||
|
||||
errfd = serrh->errorlog_fd;
|
||||
if (*serrh->fn == '|') fdevent_breakagelog_logger_pipe(errfd);
|
||||
}
|
||||
else if (!srv->srvconf.dont_daemonize) {
|
||||
/* move STDERR_FILENO to /dev/null */
|
||||
if (-1 == (errfd = fdevent_open_devnull())) {
|
||||
log_perror(srv->errh,__FILE__,__LINE__,"opening /dev/null failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*(leave STDERR_FILENO as-is)*/
|
||||
errfd = -1;
|
||||
}
|
||||
|
||||
if (0 != fdevent_set_stdin_stdout_stderr(-1, -1, errfd)) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__, "setting stderr failed");
|
||||
#ifdef FD_CLOEXEC
|
||||
if (-1 != errfd && NULL == serrh) close(errfd);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#ifdef FD_CLOEXEC
|
||||
if (-1 != errfd && NULL == serrh) close(errfd);
|
||||
#endif
|
||||
|
||||
if (NULL != serrh) {
|
||||
close(errfd); /* serrh->errorlog_fd */
|
||||
serrh->errorlog_fd = STDERR_FILENO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cycle the errorlog
|
||||
*
|
||||
*/
|
||||
|
||||
void config_log_error_cycle(server *srv) {
|
||||
/* All logs are rotated in parent and children workers so that all have
|
||||
* valid filehandles. The parent might reap a child and respawn, so the
|
||||
* parent needs valid handles for more than top-level srv->errh */
|
||||
|
||||
/*(no need to flush error log before cycling; error logs are not buffered)*/
|
||||
|
||||
config_data_base * const p = srv->config_data_base;
|
||||
|
||||
/* future: might be slightly faster to have allocated array of open files
|
||||
* rather than walking config, but only might matter with many directives */
|
||||
/* (init i to 0 if global context; to 1 to skip empty global context) */
|
||||
for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
|
||||
config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
for (; -1 != cpv->k_id; ++cpv) {
|
||||
if (cpv->vtype != T_CONFIG_LOCAL || NULL == cpv->v.v) continue;
|
||||
log_error_st *errh;
|
||||
switch (cpv->k_id) {
|
||||
case 31:/* server.errorlog */
|
||||
case 32:/* server.breakagelog */
|
||||
errh = cpv->v.v; /* cycle only if the error log is a file */
|
||||
if (errh->errorlog_mode != ERRORLOG_FILE) continue;
|
||||
if (-1 == fdevent_cycle_logger(errh->fn, &errh->errorlog_fd)) {
|
||||
/* write to top-level error log
|
||||
* (the prior log if srv->errh is the one being cycled) */
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"cycling errorlog '%s' failed", errh->fn);
|
||||
}
|
||||
else if (0 == i && errh != srv->errh) { /*(server.breakagelog)*/
|
||||
int fd = errh->errorlog_fd;
|
||||
if (STDERR_FILENO != dup2(fd, STDERR_FILENO)) {
|
||||
errh->errorlog_fd = STDERR_FILENO;
|
||||
close(fd);
|
||||
}
|
||||
else {
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"dup2() %s to STDERR failed", errh->fn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void config_log_error_close(server *srv) {
|
||||
config_data_base * const p = srv->config_data_base;
|
||||
if (NULL == p) return;
|
||||
|
||||
/* future: might be slightly faster to have allocated array of open files
|
||||
* rather than walking config, but only might matter with many directives */
|
||||
/* (init i to 0 if global context; to 1 to skip empty global context) */
|
||||
for (int i = !p->cvlist[0].v.u2[1]; i < p->nconfig; ++i) {
|
||||
config_plugin_value_t *cpv = p->cvlist + p->cvlist[i].v.u2[0];
|
||||
for (; -1 != cpv->k_id; ++cpv) {
|
||||
if (cpv->vtype != T_CONFIG_LOCAL || NULL == cpv->v.v) continue;
|
||||
log_error_st *errh = NULL;
|
||||
switch (cpv->k_id) {
|
||||
/* NB: these indexes are repeated below switch() block
|
||||
* and all must stay in sync with configfile.c */
|
||||
case 31:/* server.errorlog */
|
||||
if (0 == i) continue; /*(srv->errh is free'd later)*/
|
||||
__attribute_fallthrough__
|
||||
case 32:/* server.breakagelog */
|
||||
errh = cpv->v.v; /* cycle only if the error log is a file */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == errh) continue;
|
||||
|
||||
switch(errh->errorlog_mode) {
|
||||
case ERRORLOG_PIPE:
|
||||
case ERRORLOG_FILE:
|
||||
case ERRORLOG_FD:
|
||||
if (-1 != errh->errorlog_fd) {
|
||||
/* don't close STDERR */
|
||||
/* fdevent_close_logger_pipes() closes ERRORLOG_PIPE */
|
||||
if (STDERR_FILENO != errh->errorlog_fd
|
||||
&& ERRORLOG_PIPE != errh->errorlog_mode) {
|
||||
close(errh->errorlog_fd);
|
||||
}
|
||||
errh->errorlog_fd = -1;
|
||||
}
|
||||
break;
|
||||
case ERRORLOG_SYSLOG: /*(restricted to global scope)*/
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
closelog();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
log_error_st_free(errh);
|
||||
}
|
||||
}
|
||||
|
||||
fdevent_close_logger_pipes();
|
||||
|
||||
if (srv->errh->errorlog_mode == ERRORLOG_SYSLOG) {
|
||||
srv->errh->errorlog_mode = ERRORLOG_FD;
|
||||
srv->errh->errorlog_fd = STDERR_FILENO;
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
closelog();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -820,7 +820,8 @@ static int cgi_create_env(connection *con, plugin_data *p, handler_ctx *hctx, bu
|
|||
log_perror(con->conf.errh, __FILE__, __LINE__, "open dirname %s failed", con->physical.path->ptr);
|
||||
}
|
||||
|
||||
hctx->pid = (dfd >= 0) ? fdevent_fork_execve(args[0], args, p->env.eptr, to_cgi_fds[0], from_cgi_fds[1], -1, dfd) : -1;
|
||||
int serrh_fd = con->conf.serrh ? con->conf.serrh->errorlog_fd : -1;
|
||||
hctx->pid = (dfd >= 0) ? fdevent_fork_execve(args[0], args, p->env.eptr, to_cgi_fds[0], from_cgi_fds[1], serrh_fd, dfd) : -1;
|
||||
|
||||
if (-1 == hctx->pid) {
|
||||
/* log error with errno prior to calling close() (might change errno) */
|
||||
|
|
|
@ -786,7 +786,8 @@ static int process_ssi_stmt(connection *con, handler_ctx *p, const char **l, siz
|
|||
args[3] = NULL;
|
||||
|
||||
/*(expects STDIN_FILENO open to /dev/null)*/
|
||||
pid = fdevent_fork_execve(args[0], args, NULL, -1, c->file.fd, -1, -1);
|
||||
int serrh_fd = con->conf.serrh ? con->conf.serrh->errorlog_fd : -1;
|
||||
pid = fdevent_fork_execve(args[0], args, NULL, -1, c->file.fd, serrh_fd, -1);
|
||||
if (-1 == pid) {
|
||||
log_perror(errh, __FILE__, __LINE__, "spawning exec failed: %s", cmd);
|
||||
} else {
|
||||
|
|
|
@ -69,6 +69,15 @@ int config_finalize(server *srv, const buffer *default_server_tag);
|
|||
__attribute_cold__
|
||||
void config_free(server *srv);
|
||||
|
||||
__attribute_cold__
|
||||
int config_log_error_open(server *srv);
|
||||
|
||||
__attribute_cold__
|
||||
void config_log_error_cycle(server *srv);
|
||||
|
||||
__attribute_cold__
|
||||
void config_log_error_close(server *srv);
|
||||
|
||||
void config_reset_config_bytes_sec(void *p);
|
||||
|
||||
void config_reset_config(connection *con);
|
||||
|
|
224
src/server.c
224
src/server.c
|
@ -58,10 +58,6 @@ static const buffer default_server_tag = { CONST_STR_LEN(PACKAGE_DESC), 0 };
|
|||
# include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_LOADAVG_H
|
||||
# include <sys/loadavg.h>
|
||||
#endif
|
||||
|
@ -87,11 +83,6 @@ static const buffer default_server_tag = { CONST_STR_LEN(PACKAGE_DESC), 0 };
|
|||
/* #define USE_ALARM */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PLUGIN_DATA;
|
||||
specific_config defaults;
|
||||
} config_data_base;
|
||||
|
||||
static int oneshot_fd = 0;
|
||||
static volatile int pid_fd = -2;
|
||||
static server_socket_array graceful_sockets;
|
||||
|
@ -538,212 +529,6 @@ static void show_help (void) {
|
|||
write_all(STDOUT_FILENO, b, strlen(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* open the errorlog
|
||||
*
|
||||
* we have 4 possibilities:
|
||||
* - stderr (default)
|
||||
* - syslog
|
||||
* - logfile
|
||||
* - pipe
|
||||
*
|
||||
*/
|
||||
|
||||
static void log_error_open_syslog(server *srv, log_error_st *errh, const buffer *syslog_facility) {
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
errh->errorlog_mode = ERRORLOG_SYSLOG;
|
||||
/* perhaps someone wants to use syslog() */
|
||||
int facility = -1;
|
||||
if (!buffer_string_is_empty(syslog_facility)) {
|
||||
static const struct facility_name_st {
|
||||
const char *name;
|
||||
int val;
|
||||
} facility_names[] = {
|
||||
{ "auth", LOG_AUTH }
|
||||
#ifdef LOG_AUTHPRIV
|
||||
,{ "authpriv", LOG_AUTHPRIV }
|
||||
#endif
|
||||
#ifdef LOG_CRON
|
||||
,{ "cron", LOG_CRON }
|
||||
#endif
|
||||
,{ "daemon", LOG_DAEMON }
|
||||
#ifdef LOG_FTP
|
||||
,{ "ftp", LOG_FTP }
|
||||
#endif
|
||||
#ifdef LOG_KERN
|
||||
,{ "kern", LOG_KERN }
|
||||
#endif
|
||||
#ifdef LOG_LPR
|
||||
,{ "lpr", LOG_LPR }
|
||||
#endif
|
||||
#ifdef LOG_MAIL
|
||||
,{ "mail", LOG_MAIL }
|
||||
#endif
|
||||
#ifdef LOG_NEWS
|
||||
,{ "news", LOG_NEWS }
|
||||
#endif
|
||||
,{ "security", LOG_AUTH } /* DEPRECATED */
|
||||
#ifdef LOG_SYSLOG
|
||||
,{ "syslog", LOG_SYSLOG }
|
||||
#endif
|
||||
#ifdef LOG_USER
|
||||
,{ "user", LOG_USER }
|
||||
#endif
|
||||
#ifdef LOG_UUCP
|
||||
,{ "uucp", LOG_UUCP }
|
||||
#endif
|
||||
,{ "local0", LOG_LOCAL0 }
|
||||
,{ "local1", LOG_LOCAL1 }
|
||||
,{ "local2", LOG_LOCAL2 }
|
||||
,{ "local3", LOG_LOCAL3 }
|
||||
,{ "local4", LOG_LOCAL4 }
|
||||
,{ "local5", LOG_LOCAL5 }
|
||||
,{ "local6", LOG_LOCAL6 }
|
||||
,{ "local7", LOG_LOCAL7 }
|
||||
};
|
||||
for (unsigned int i = 0; i < sizeof(facility_names)/sizeof(facility_names[0]); ++i) {
|
||||
const struct facility_name_st *f = facility_names+i;
|
||||
if (0 == strcmp(syslog_facility->ptr, f->name)) {
|
||||
facility = f->val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == facility) {
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"unrecognized server.syslog-facility: \"%s\"; "
|
||||
"defaulting to \"daemon\" facility",
|
||||
syslog_facility->ptr);
|
||||
}
|
||||
}
|
||||
openlog("lighttpd", LOG_CONS|LOG_PID, -1==facility ? LOG_DAEMON : facility);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int log_error_open_fn(server *srv, log_error_st *errh, const char *fn) {
|
||||
int fd = fdevent_open_logger(fn);
|
||||
if (-1 == fd) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"opening errorlog '%s' failed", fn);
|
||||
return -1;
|
||||
}
|
||||
errh->errorlog_fd = fd;
|
||||
errh->errorlog_mode = fn[0] == '|' ? ERRORLOG_PIPE : ERRORLOG_FILE;
|
||||
errh->fn = fn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int log_error_open_breakagelog(server *srv) {
|
||||
log_error_st * const errh = srv->errh;
|
||||
int errfd;
|
||||
if (!buffer_string_is_empty(srv->srvconf.breakagelog_file)) {
|
||||
const char *logfile = srv->srvconf.breakagelog_file->ptr;
|
||||
|
||||
if (errh->errorlog_mode == ERRORLOG_FD) {
|
||||
errh->errorlog_fd = dup(STDERR_FILENO);
|
||||
fdevent_setfd_cloexec(errh->errorlog_fd);
|
||||
}
|
||||
|
||||
if (-1 == (errfd = fdevent_open_logger(logfile))) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"opening errorlog '%s' failed", logfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*logfile == '|') fdevent_breakagelog_logger_pipe(errfd);
|
||||
}
|
||||
else if (!srv->srvconf.dont_daemonize) {
|
||||
/* move STDERR_FILENO to /dev/null */
|
||||
if (-1 == (errfd = fdevent_open_devnull())) {
|
||||
log_perror(srv->errh,__FILE__,__LINE__,"opening /dev/null failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*(leave STDERR_FILENO as-is)*/
|
||||
errfd = -1;
|
||||
}
|
||||
|
||||
if (0 != fdevent_set_stdin_stdout_stderr(-1, -1, errfd)) {
|
||||
log_perror(srv->errh, __FILE__, __LINE__, "setting stderr failed");
|
||||
#ifdef FD_CLOEXEC
|
||||
if (-1 != errfd) close(errfd);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
#ifdef FD_CLOEXEC
|
||||
if (-1 != errfd) close(errfd);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int log_error_open(server *srv) {
|
||||
if (srv->srvconf.errorlog_use_syslog) {
|
||||
log_error_open_syslog(srv, srv->errh, srv->srvconf.syslog_facility);
|
||||
}
|
||||
else if (!buffer_string_is_empty(srv->srvconf.errorlog_file)) {
|
||||
if (-1 == log_error_open_fn(srv, srv->errh,
|
||||
srv->srvconf.errorlog_file->ptr))
|
||||
return -1;
|
||||
}
|
||||
else if (srv->errh->errorlog_mode == ERRORLOG_FD
|
||||
&& !srv->srvconf.dont_daemonize) {
|
||||
/* We can only log to stderr in dont-daemonize mode;
|
||||
* if we do daemonize and no errorlog file is specified,
|
||||
* we log into /dev/null
|
||||
*/
|
||||
srv->errh->errorlog_fd = -1;
|
||||
}
|
||||
|
||||
return log_error_open_breakagelog(srv);
|
||||
}
|
||||
|
||||
/**
|
||||
* cycle the errorlog
|
||||
*
|
||||
*/
|
||||
|
||||
static void log_error_cycle(server *srv) {
|
||||
/* cycle only if the error log is a file */
|
||||
|
||||
log_error_st * const errh = srv->errh;
|
||||
if (errh->errorlog_mode == ERRORLOG_FILE) {
|
||||
if (-1 == fdevent_cycle_logger(errh->fn, &errh->errorlog_fd)) {
|
||||
/* write to old log */
|
||||
log_perror(srv->errh, __FILE__, __LINE__,
|
||||
"cycling errorlog '%s' failed", errh->fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute_cold__
|
||||
static int log_error_close(server *srv) {
|
||||
log_error_st *errh = srv->errh;
|
||||
switch(errh->errorlog_mode) {
|
||||
case ERRORLOG_PIPE:
|
||||
case ERRORLOG_FILE:
|
||||
case ERRORLOG_FD:
|
||||
if (-1 != errh->errorlog_fd) {
|
||||
/* don't close STDERR */
|
||||
/* fdevent_close_logger_pipes() closes ERRORLOG_PIPE */
|
||||
if (STDERR_FILENO != errh->errorlog_fd
|
||||
&& ERRORLOG_PIPE != errh->errorlog_mode) {
|
||||
close(errh->errorlog_fd);
|
||||
}
|
||||
errh->errorlog_fd = -1;
|
||||
}
|
||||
break;
|
||||
case ERRORLOG_SYSLOG:
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
closelog();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute_cold__
|
||||
static void server_sockets_save (server *srv) { /* graceful_restart */
|
||||
memcpy(&graceful_sockets, &srv->srv_sockets, sizeof(server_socket_array));
|
||||
|
@ -1350,7 +1135,7 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
/* Close stderr ASAP in the child process to make sure that nothing
|
||||
* is being written to that fd which may not be valid anymore. */
|
||||
if (!srv->srvconf.preflight_check) {
|
||||
if (-1 == log_error_open(srv)) {
|
||||
if (-1 == config_log_error_open(srv)) {
|
||||
log_error(srv->errh, __FILE__, __LINE__, "Opening errorlog failed. Going down.");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1452,7 +1237,7 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
if (handle_sig_hup) {
|
||||
handle_sig_hup = 0;
|
||||
|
||||
log_error_cycle(srv);
|
||||
config_log_error_cycle(srv);
|
||||
|
||||
/* forward SIGHUP to workers */
|
||||
for (int n = 0; n < npids; ++n) {
|
||||
|
@ -1597,7 +1382,7 @@ static void server_handle_sighup (server * const srv) {
|
|||
|
||||
plugins_call_handle_sighup(srv);
|
||||
|
||||
log_error_cycle(srv);
|
||||
config_log_error_cycle(srv);
|
||||
#ifdef HAVE_SIGACTION
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"logfiles cycled UID = %d PID = %d",
|
||||
|
@ -1783,8 +1568,7 @@ int main (int argc, char **argv) {
|
|||
|
||||
/* clean-up */
|
||||
remove_pid_file(srv);
|
||||
log_error_close(srv);
|
||||
fdevent_close_logger_pipes();
|
||||
config_log_error_close(srv);
|
||||
if (graceful_restart)
|
||||
server_sockets_save(srv);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue