Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core/angel] add pipe logging #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/lighttpd/angel.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ LI_API void li_angel_listen(liServer *srv, GString *str, liAngelListenCB cb, gpo
LI_API void li_angel_log(liServer *srv, GString *str);

LI_API void li_angel_log_open_file(liServer *srv, GString *filename, liAngelLogOpen, gpointer data);
LI_API void li_angel_log_open_pipe(liServer *srv, GString *filename, liAngelLogOpen, gpointer data);

/* angle_fake definitions, only for internal use */
int li_angel_fake_listen(liServer *srv, GString *str);
Expand Down
1 change: 1 addition & 0 deletions include/lighttpd/angel_plugin_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct liPluginCoreConfig {
gboolean load_failed;
liInstanceConf *load_instconf;
GPtrArray *load_listen_masks;
GHashTable *load_pipes;

/* Running */
liInstanceConf *instconf;
Expand Down
82 changes: 82 additions & 0 deletions src/angel/angel_plugin_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static void core_instance_parse(liServer *srv, liPlugin *p, liValue **options) {
gid_t gid = -1;
GString *user = NULL;
gint64 rlim_core = -1, rlim_nofile = -1;
liValue *lv = NULL;

if (config->load_instconf) {
ERROR(srv, "%s", "Already configure the instance");
Expand Down Expand Up @@ -185,6 +186,13 @@ static void core_instance_parse(liServer *srv, liPlugin *p, liValue **options) {
if (options[9]) rlim_core = options[9]->data.number;
if (options[10]) rlim_nofile = options[10]->data.number;

if (options[11]) {
lv = li_value_copy(options[11]);
config->load_pipes = lv->data.hash;
lv->type = LI_VALUE_NONE;
li_value_free(lv);
}

g_ptr_array_add(cmd, NULL);
g_ptr_array_add(env, NULL);
cmdarr = (gchar**) g_ptr_array_free(cmd, FALSE);
Expand All @@ -204,6 +212,7 @@ static const liPluginItemOption core_instance_options[] = {
/* 8 */ { "copy-env", LI_VALUE_LIST, 0 },
/* 9 */ { "max-core-file-size", LI_VALUE_NUMBER, 0 },
/* 10 */ { "max-open-files", LI_VALUE_NUMBER, 0 },
/* 11 */ { "pipes", LI_VALUE_HASH, 0 },
{ NULL, 0, 0 }
};

Expand Down Expand Up @@ -668,6 +677,75 @@ static void core_log_open_file(liServer *srv, liPlugin *p, liInstance *i, gint32
}
}

static void core_log_open_pipe(liServer *srv, liPlugin *p, liInstance *i, gint32 id, GString *data) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
liValue *pipeval = NULL;

GError *err = NULL;
int fd = -1;
GArray *fds;

int to_log_fds[2];
pid_t pid;

DEBUG(srv, "core_log_open_pipe(%i, '%s')", id, data->str);

if (-1 == id) return; /* ignore simple calls */

pipeval = g_hash_table_lookup(config->load_pipes, data);
if (pipeval) {
if (!pipe(to_log_fds)) {
switch (pid = fork()) {
case 0:
close(STDIN_FILENO);
dup2(to_log_fds[0], STDIN_FILENO);
close(to_log_fds[0]);
close(to_log_fds[1]);
execl("/bin/sh", "sh", "-c", pipeval->data.string->str, (char*)NULL);
ERROR(srv, "core_log_open_pipe(%i, '%s'): execl failed (%s)", id, data->str, strerror(errno));
exit(-1);
break;
case -1:
ERROR(srv, "core_log_open_pipe(%i, '%s'): fork failed (%s)", id, data->str, strerror(errno));
break;
default:
close(to_log_fds[0]);
fd = to_log_fds[1];
break;
}
}
if (-1 == fd) {
int e = errno;
GString *error = g_string_sized_new(0);
g_string_printf(error, "Couldn't open log file '%s': '%s'", data->str, g_strerror(e));
ERROR(srv, "Couldn't open log file '%s': %s", data->str, g_strerror(e));
if (!li_angel_send_result(i->acon, id, error, NULL, NULL, &err)) {
ERROR(srv, "Couldn't send result: %s", err->message);
g_error_free(err);
}
return;
}
} else {
GString *error = g_string_sized_new(0);
g_string_printf(error, "Couldn't open log pipe '%s': unconfigured pipe", data->str);

if (!li_angel_send_result(i->acon, id, error, NULL, NULL, &err)) {
ERROR(srv, "Couldn't send result: %s", err->message);
g_error_free(err);
}
return;
}

fds = g_array_new(FALSE, FALSE, sizeof(int));
g_array_append_val(fds, fd);

if (!li_angel_send_result(i->acon, id, NULL, NULL, fds, &err)) {
ERROR(srv, "Couldn't send result: %s", err->message);
g_error_free(err);
return;
}
}

static void core_clean(liServer *srv, liPlugin *p);
static void core_free(liServer *srv, liPlugin *p) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
Expand All @@ -693,6 +771,8 @@ static void core_free(liServer *srv, liPlugin *p) {
}
g_ptr_array_free(config->listen_masks, TRUE);
g_ptr_array_free(config->load_listen_masks, TRUE);
if (config->load_pipes != NULL)
g_hash_table_destroy(config->load_pipes);
g_hash_table_destroy(config->listen_sockets);
config->listen_masks = NULL;
config->load_listen_masks = NULL;
Expand Down Expand Up @@ -798,11 +878,13 @@ static gboolean core_init(liServer *srv, liPlugin *p) {

config->listen_masks = g_ptr_array_new();
config->load_listen_masks = g_ptr_array_new();
config->load_pipes = NULL;
config->listen_sockets = g_hash_table_new_full(li_hash_sockaddr, li_equal_sockaddr, NULL, _listen_socket_free);

li_angel_plugin_add_angel_cb(p, "listen", core_listen);
li_angel_plugin_add_angel_cb(p, "reached-state", core_reached_state);
li_angel_plugin_add_angel_cb(p, "log-open-file", core_log_open_file);
li_angel_plugin_add_angel_cb(p, "log-open-pipe", core_log_open_pipe);

ev_signal_init(&config->sig_hup, core_handle_sig_hup, SIGHUP);
config->sig_hup.data = config;
Expand Down
21 changes: 21 additions & 0 deletions src/main/angel.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,24 @@ void li_angel_log_open_file(liServer *srv, GString *filename, liAngelLogOpen cb,
cb(srv, fd, data);
}
}

void li_angel_log_open_pipe(liServer *srv, GString *pipename, liAngelLogOpen cb, gpointer data) {
if (srv->acon) {
liAngelCall *acall = li_angel_call_new(li_angel_log_open_cb, 10.0);
angel_log_cb_ctx *ctx = g_slice_new0(angel_log_cb_ctx);
GError *err = NULL;

ctx->srv = srv;
ctx->cb = cb;
ctx->data = data;
ctx->logname = g_string_new_len(GSTR_LEN(pipename));

acall->context = ctx;
if (!li_angel_send_call(srv->acon, CONST_STR_LEN("core"), CONST_STR_LEN("log-open-pipe"), acall, g_string_new_len(GSTR_LEN(pipename)), &err)) {
ERROR(srv, "couldn't send call: %s", err->message);
g_error_free(err);
}
} else {
ERROR(srv, "angel required for: %s", "log-open-pipe");
}
}
29 changes: 21 additions & 8 deletions src/main/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ static void li_log_write_stderr(liServer *srv, const gchar *msg, gboolean newlin
g_static_mutex_unlock(&mtx);
}

static void log_open_pipe_cb(liServer *srv, int fd, gpointer data) {
liLogTarget *log;
log = data;

if (log == NULL)
ERROR(srv, "log_open_pipe_cb(%d, %s): no log found", fd, log->path->str);
else if (log->fd < 0)
log->fd = fd;
}

static liLogTarget *log_open(liServer *srv, GString *path) {
liLogTarget *log;

Expand All @@ -50,6 +60,14 @@ static liLogTarget *log_open(liServer *srv, GString *path) {
liLogType type = li_log_type_from_path(path, &param);
GString sparam = { param, (param != NULL ? path->len - (param - path->str) : 0), 0 };

if (type == LI_LOG_TYPE_NONE) return NULL;

/* Even if -1 == fd we create an entry, so we don't throw an error every time */
log = g_slice_new0(liLogTarget);
log->type = type;
log->path = g_string_new_len(GSTR_LEN(path));
log->wqelem.data = log;

switch (type) {
case LI_LOG_TYPE_STDERR:
fd = STDERR_FILENO;
Expand All @@ -59,21 +77,14 @@ static liLogTarget *log_open(liServer *srv, GString *path) {
fd = li_angel_fake_log_open_file(srv, &sparam);
break;
case LI_LOG_TYPE_PIPE:
ERROR(srv, "%s", "pipe logging not supported yet");
li_angel_log_open_pipe(srv, &sparam, log_open_pipe_cb, log);
break;
case LI_LOG_TYPE_SYSLOG:
ERROR(srv, "%s", "syslog not supported yet");
break;
case LI_LOG_TYPE_NONE:
return NULL;
}

/* Even if -1 == fd we create an entry, so we don't throw an error every time */
log = g_slice_new0(liLogTarget);
log->type = type;
log->path = g_string_new_len(GSTR_LEN(path));
log->fd = fd;
log->wqelem.data = log;
li_radixtree_insert(srv->logs.targets, log->path->str, log->path->len * 8, log);
/*g_print("log_open(\"%s\")\n", log->path->str);*/
}
Expand Down Expand Up @@ -374,6 +385,8 @@ static void log_watcher_cb(struct ev_loop *loop, ev_async *w, int revents) {
continue;
}

if (log->type == LI_LOG_TYPE_PIPE)
log_close(srv, log);
str = g_string_sized_new(63);
g_string_printf(str, "could not write to log '%s': %s\n", log_entry->path->str, g_strerror(err));
li_log_write_stderr(srv, str->str, TRUE);
Expand Down