2
0

Compare commits

..

7 Commits

Author SHA1 Message Date
10f54c2d83 [core] don't release mainaction before stopping workers
This reverts commit f2ade38923.

Running workers will try to handle connections, and thus changing
mainaction without locking is a race condition, and also we don't handle
a NULL mainaction properly and segfault.

Given running connections will keep mainaction alive anyway, it is
unclear what the purpose of releasing it early was in the first place.

Change-Id: I2266958520c3cfca28c5c19574abdf44ddf6b0bc
2023-09-08 15:53:41 +02:00
dca280076b [angel] improve instance related logging
Change-Id: Ie58d07ae441100299c75aeb657000fdcf828036d
2023-09-08 15:24:51 +02:00
522a9e221b [angel] improve startup/stop logging
Change-Id: I71666d8f37edf1246a58daa880b3fa64316d801f
2023-09-08 15:14:49 +02:00
a19d73ecd5 [angel] server_module not shared anymore, drop refcount handling
Change-Id: I65cd3cb1409238537299e0654fb681ab5286b43f
2023-09-08 15:14:49 +02:00
0ced2aa60a [angel] remove config reload handling, don't unload plugins while instance is running
* config reload wasn't actually available; but internal code existed
  trying to handle it:
  * it would load new plugins and unload old plugins
  * state of old plugins might be in use by running instances
* server stop was implemented as "loading empty config" (without core
  plugin)
* NULL-derefs/segfaults on exit when instances tried to access plugin
  data that was already gone

As we only load a single config: drop this completely, and replace
"cleanup pending config" (to handle config reload errors) with "stop"
callback in plugins.

Change-Id: I204441fb9f54e22d2b0d31ed18d0c188fe7150ac
2023-09-08 15:14:49 +02:00
b4102fed4c [angel] move plugin core types to implementation
Change-Id: I912934be6e0d20b2c12c17bf7e007198b49bfb0c
2023-09-08 15:14:49 +02:00
87a7339b49 [angel] fix small memory leak from config loading
Change-Id: I2aa174c220543a7bcc011118eaaf4b0925b4aa19
2023-09-08 15:14:45 +02:00
9 changed files with 176 additions and 215 deletions

View File

@ -11,6 +11,7 @@ typedef struct liPlugins liPlugins;
typedef gboolean (*liPluginInitCB) (liServer *srv, liPlugin *p); typedef gboolean (*liPluginInitCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginFreeCB) (liServer *srv, liPlugin *p); typedef void (*liPluginFreeCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginStopCB) (liServer *srv, liPlugin *p);
typedef void (*liPluginCleanConfigCB) (liServer *srv, liPlugin *p); typedef void (*liPluginCleanConfigCB) (liServer *srv, liPlugin *p);
typedef gboolean (*liPluginCheckConfigCB) (liServer *srv, liPlugin *p, GError **err); typedef gboolean (*liPluginCheckConfigCB) (liServer *srv, liPlugin *p, GError **err);
@ -37,8 +38,8 @@ struct liPlugin {
GHashTable *angel_callbacks; /**< map (const gchar*) -> liPluginHandleCallCB */ GHashTable *angel_callbacks; /**< map (const gchar*) -> liPluginHandleCallCB */
liPluginFreeCB handle_free; /**< called before plugin is unloaded */ liPluginFreeCB handle_free; /**< called before plugin is unloaded */
liPluginStopCB handle_stop; /**< called to stop server */
liPluginCleanConfigCB handle_clean_config; /**< called before the reloading of the config is started or after the reloading failed */
liPluginCheckConfigCB handle_check_config; /**< called before activating a config to ensure everything works */ liPluginCheckConfigCB handle_check_config; /**< called before activating a config to ensure everything works */
liPluginActivateConfigCB handle_activate_config; /**< called to activate a config after successful loading it. this cannot fail */ liPluginActivateConfigCB handle_activate_config; /**< called to activate a config after successful loading it. this cannot fail */
@ -49,21 +50,21 @@ struct liPlugin {
struct liPlugins { struct liPlugins {
GString *config_filename; GString *config_filename;
GHashTable *items, *load_items; /**< gchar* -> server_item */ GHashTable *items; /**< gchar* -> server_item */
liModules *modules; liModules *modules;
GHashTable *module_refs, *load_module_refs; /** gchar* -> server_module */ GHashTable *module_refs; /** gchar* -> server_module */
GHashTable *ht_plugins, *load_ht_plugins; GHashTable *ht_plugins;
GPtrArray *plugins, *load_plugins; /* plugin* */ GPtrArray *plugins; /* plugin* */
}; };
LI_API void li_plugins_init(liServer *srv, const gchar *module_dir, gboolean module_resident); LI_API void li_plugins_init(liServer *srv, const gchar *module_dir, gboolean module_resident);
LI_API void li_plugins_clear(liServer *srv); LI_API void li_plugins_clear(liServer *srv);
LI_API void li_plugins_config_clean(liServer *srv);
LI_API gboolean li_plugins_config_load(liServer *srv, const gchar *filename); LI_API gboolean li_plugins_config_load(liServer *srv, const gchar *filename);
LI_API void li_plugins_stop(liServer *srv);
LI_API gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *parameters, GError **err); LI_API gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *parameters, GError **err);

View File

@ -3,70 +3,6 @@
#include <lighttpd/angel_base.h> #include <lighttpd/angel_base.h>
typedef struct liPluginCoreParsing liPluginCoreParsing;
struct liPluginCoreParsing {
GPtrArray *env; /* <gchar*> */
GString *user;
uid_t user_uid;
gid_t user_gid;
GString *group;
gid_t group_gid;
GString *binary;
GString *config;
GString *luaconfig;
GString *modules_path;
GPtrArray *wrapper; /* <gchar*> */
gint64 rlim_core, rlim_nofile;
liInstanceConf *instconf;
GPtrArray *listen_masks;
};
typedef struct liPluginCoreConfig liPluginCoreConfig;
struct liPluginCoreConfig {
/* Parsing/Load */
liPluginCoreParsing parsing;
/* Running */
liInstanceConf *instconf;
GPtrArray *listen_masks;
liInstance *inst;
GHashTable *listen_sockets;
liEventSignal sig_hup;
};
typedef struct liPluginCoreListenMask liPluginCoreListenMask;
struct liPluginCoreListenMask {
enum {
LI_PLUGIN_CORE_LISTEN_MASK_IPV4,
LI_PLUGIN_CORE_LISTEN_MASK_IPV6,
LI_PLUGIN_CORE_LISTEN_MASK_UNIX
} type;
union {
struct {
guint32 addr;
guint32 networkmask;
guint16 port;
} ipv4;
struct {
guint8 addr[16];
guint network;
guint16 port;
} ipv6;
struct {
GString *path;
} unix_socket;
} value;
};
LI_API gboolean li_plugin_core_init(liServer *srv); LI_API gboolean li_plugin_core_init(liServer *srv);
#endif #endif

View File

@ -29,6 +29,7 @@ struct liInstance {
liServer *srv; liServer *srv;
liInstanceConf *ic; liInstanceConf *ic;
int pid; /** < remember PID for process as instance ID, even if process is already gone */
liProc *proc; liProc *proc;
liEventChild child_watcher; liEventChild child_watcher;

View File

@ -387,6 +387,7 @@ static gboolean tokenizer_init_file(liServer *srv, liConfigTokenizerContext *ctx
static void tokenizer_clear(liConfigTokenizerContext *ctx) { static void tokenizer_clear(liConfigTokenizerContext *ctx) {
g_string_free(ctx->token_string, TRUE); g_string_free(ctx->token_string, TRUE);
g_hash_table_destroy(ctx->variables);
} }
static liConfigToken tokenizer_next(liConfigTokenizerContext *ctx, GError **error) { static liConfigToken tokenizer_next(liConfigTokenizerContext *ctx, GError **error) {

View File

@ -87,8 +87,6 @@ int main(int argc, char *argv[]) {
goto cleanup; goto cleanup;
} }
INFO(srv, "%s", "parsed config file");
li_event_loop_run(&srv->loop); li_event_loop_run(&srv->loop);
INFO(srv, "%s", "going down"); INFO(srv, "%s", "going down");

View File

@ -13,7 +13,6 @@ struct server_item {
typedef struct server_module server_module; typedef struct server_module server_module;
struct server_module { struct server_module {
guint refcount;
gchar *name; gchar *name;
liServer *srv; liServer *srv;
liModule *mod; liModule *mod;
@ -48,9 +47,6 @@ static void _server_module_release(gpointer d) {
server_module *sm = d; server_module *sm = d;
guint i; guint i;
g_assert(sm->refcount > 0);
if (0 != --sm->refcount) return;
for (i = sm->plugins->len; i-- > 0; ) { for (i = sm->plugins->len; i-- > 0; ) {
liPlugin *p = g_ptr_array_index(sm->plugins, i); liPlugin *p = g_ptr_array_index(sm->plugins, i);
li_plugin_free(sm->srv, p); li_plugin_free(sm->srv, p);
@ -61,14 +57,8 @@ static void _server_module_release(gpointer d) {
g_slice_free(server_module, sm); g_slice_free(server_module, sm);
} }
static void server_module_acquire(server_module *sm) {
g_assert(sm->refcount > 0);
sm->refcount++;
}
static server_module* server_module_new(liServer *srv, const gchar *name) { /* module is set later */ static server_module* server_module_new(liServer *srv, const gchar *name) { /* module is set later */
server_module *sm = g_slice_new0(server_module); server_module *sm = g_slice_new0(server_module);
sm->refcount = 1;
sm->srv = srv; sm->srv = srv;
sm->plugins = g_ptr_array_new(); sm->plugins = g_ptr_array_new();
sm->name = g_strdup(name); sm->name = g_strdup(name);
@ -81,124 +71,90 @@ void li_plugins_init(liServer *srv, const gchar *module_dir, gboolean module_res
ps->modules = li_modules_new(srv, module_dir, module_resident); ps->modules = li_modules_new(srv, module_dir, module_resident);
ps->items = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_item_free); ps->items = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_item_free);
ps->load_items = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_item_free);
ps->module_refs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_module_release); ps->module_refs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_module_release);
ps->load_module_refs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, _server_module_release);
ps->ht_plugins = g_hash_table_new(g_str_hash, g_str_equal); ps->ht_plugins = g_hash_table_new(g_str_hash, g_str_equal);
ps->load_ht_plugins = g_hash_table_new(g_str_hash, g_str_equal);
ps->plugins = g_ptr_array_new(); ps->plugins = g_ptr_array_new();
ps->load_plugins = g_ptr_array_new();
} }
void li_plugins_clear(liServer *srv) { void li_plugins_clear(liServer *srv) {
liPlugins *ps = &srv->plugins; liPlugins *ps = &srv->plugins;
li_plugins_config_clean(srv);
g_hash_table_destroy(ps->items); g_hash_table_destroy(ps->items);
g_hash_table_destroy(ps->load_items);
g_hash_table_destroy(ps->module_refs); g_hash_table_destroy(ps->module_refs);
g_hash_table_destroy(ps->load_module_refs);
g_hash_table_destroy(ps->ht_plugins); g_hash_table_destroy(ps->ht_plugins);
g_hash_table_destroy(ps->load_ht_plugins);
g_ptr_array_free(ps->plugins, TRUE); g_ptr_array_free(ps->plugins, TRUE);
g_ptr_array_free(ps->load_plugins, TRUE);
if (ps->config_filename) g_string_free(ps->config_filename, TRUE); if (ps->config_filename) g_string_free(ps->config_filename, TRUE);
li_modules_free(ps->modules); li_modules_free(ps->modules);
} }
void li_plugins_config_clean(liServer *srv) {
liPlugins *ps = &srv->plugins;
guint i;
for (i = ps->load_plugins->len; i-- > 0; ) {
liPlugin *p = g_ptr_array_index(ps->load_plugins, i);
if (p->handle_clean_config) p->handle_clean_config(srv, p);
}
g_hash_table_remove_all(ps->load_items);
g_hash_table_remove_all(ps->load_module_refs);
g_hash_table_remove_all(ps->load_ht_plugins);
g_ptr_array_set_size(ps->load_plugins, 0);
}
gboolean li_plugins_config_load(liServer *srv, const gchar *filename) { gboolean li_plugins_config_load(liServer *srv, const gchar *filename) {
liPlugins *ps = &srv->plugins; liPlugins *ps = &srv->plugins;
GError *error = NULL; GError *error = NULL;
guint i; guint i;
if (filename) { if (!li_plugins_load_module(srv, NULL)) {
if (!li_plugins_load_module(srv, NULL)) { ERROR(srv, "%s", "failed loading core plugins");
ERROR(srv, "%s", "failed loading core plugins"); return FALSE;
li_plugins_config_clean(srv);
return FALSE;
}
if (!li_angel_config_parse_file(srv, filename, &error)) {
ERROR(srv, "failed to parse config file: %s", error->message);
g_error_free(error);
li_plugins_config_clean(srv);
return FALSE;
}
} }
if (!li_angel_config_parse_file(srv, filename, &error)) {
ERROR(srv, "failed to parse config file: %s", error->message);
g_error_free(error);
return FALSE;
}
DEBUG(srv, "parsed config file: %s", filename);
/* check new config */ /* check new config */
for (i = ps->load_plugins->len; i-- > 0; ) { for (i = ps->plugins->len; i-- > 0; ) {
liPlugin *p = g_ptr_array_index(ps->load_plugins, i); liPlugin *p = g_ptr_array_index(ps->plugins, i);
if (p->handle_check_config) { if (p->handle_check_config) {
if (!p->handle_check_config(srv, p, &error)) { if (!p->handle_check_config(srv, p, &error)) {
ERROR(srv, "config check failed: %s", error->message); ERROR(srv, "config check failed: %s", error->message);
g_error_free(error); g_error_free(error);
li_plugins_config_clean(srv);
return FALSE; return FALSE;
} }
} }
} }
INFO(srv, "%s", "activate");
/* activate new config */ /* activate new config */
for (i = ps->load_plugins->len; i-- > 0; ) { for (i = ps->plugins->len; i-- > 0; ) {
liPlugin *p = g_ptr_array_index(ps->load_plugins, i); liPlugin *p = g_ptr_array_index(ps->plugins, i);
INFO(srv, "activate: %s", p->name); DEBUG(srv, "activate plugin: %s", p->name);
if (p->handle_activate_config) { if (p->handle_activate_config) {
p->handle_activate_config(srv, p); p->handle_activate_config(srv, p);
} }
} }
INFO(srv, "%s", "done"); DEBUG(srv, "%s", "config loading done");
{ /* swap the arrays */ LI_FORCE_ASSERT(NULL == ps->config_filename);
GPtrArray *tmp = ps->load_plugins; ps->load_plugins = ps->plugins; ps->plugins = tmp; ps->config_filename = g_string_new(filename);
}
{ /* swap the hash tables */
GHashTable *tmp;
tmp = ps->load_items; ps->load_items = ps->items; ps->items = tmp;
tmp = ps->load_module_refs; ps->load_module_refs = ps->module_refs; ps->module_refs = tmp;
tmp = ps->load_ht_plugins; ps->load_ht_plugins = ps->ht_plugins; ps->ht_plugins = tmp;
}
g_hash_table_remove_all(ps->load_items);
g_hash_table_remove_all(ps->load_module_refs);
g_hash_table_remove_all(ps->load_ht_plugins);
g_ptr_array_set_size(ps->load_plugins, 0);
if (!ps->config_filename) {
ps->config_filename = g_string_new(filename);
} else {
g_string_assign(ps->config_filename, filename ? filename : "");
}
return TRUE; return TRUE;
} }
void li_plugins_stop(liServer *srv) {
liPlugins *ps = &srv->plugins;
guint i;
g_string_assign(ps->config_filename, "");
/* activate new config */
for (i = ps->plugins->len; i-- > 0; ) {
liPlugin *p = g_ptr_array_index(ps->plugins, i);
INFO(srv, "stop: %s", p->name);
if (p->handle_stop) {
p->handle_stop(srv, p);
}
}
}
gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *parameters, GError **err) { gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *parameters, GError **err) {
liPlugins *ps = &srv->plugins; liPlugins *ps = &srv->plugins;
server_item *si; server_item *si;
@ -212,7 +168,7 @@ gboolean li_plugins_handle_item(liServer *srv, GString *itemname, liValue *param
} }
#endif #endif
si = g_hash_table_lookup(ps->load_items, itemname->str); si = g_hash_table_lookup(ps->items, itemname->str);
if (!si) { if (!si) {
g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE, g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE,
"Unknown item '%s' - perhaps you forgot to load the module?", itemname->str); "Unknown item '%s' - perhaps you forgot to load the module?", itemname->str);
@ -230,19 +186,19 @@ static gboolean plugins_activate_module(liServer *srv, server_module *sm) {
for (i = 0; i < sm->plugins->len; i++) { for (i = 0; i < sm->plugins->len; i++) {
p = g_ptr_array_index(sm->plugins, i); p = g_ptr_array_index(sm->plugins, i);
g_ptr_array_add(ps->load_plugins, p); g_ptr_array_add(ps->plugins, p);
g_hash_table_insert(ps->load_ht_plugins, (gpointer) p->name, p); g_hash_table_insert(ps->ht_plugins, (gpointer) p->name, p);
if (!p->items) continue; if (!p->items) continue;
for (pi = p->items; pi->name; pi++) { for (pi = p->items; pi->name; pi++) {
server_item *si; server_item *si;
if (NULL != (si = g_hash_table_lookup(ps->load_items, pi->name))) { if (NULL != (si = g_hash_table_lookup(ps->items, pi->name))) {
ERROR(srv, "Plugin item name conflict: cannot load '%s' for plugin '%s' (already provided by plugin '%s')", ERROR(srv, "Plugin item name conflict: cannot load '%s' for plugin '%s' (already provided by plugin '%s')",
pi->name, p->name, si->p->name); pi->name, p->name, si->p->name);
goto item_collision; goto item_collision;
} else { } else {
si = server_item_new(p, pi); si = server_item_new(p, pi);
g_hash_table_insert(ps->load_items, (gpointer) pi->name, si); g_hash_table_insert(ps->items, (gpointer) pi->name, si);
} }
} }
} }
@ -252,18 +208,18 @@ static gboolean plugins_activate_module(liServer *srv, server_module *sm) {
item_collision: item_collision:
/* removed added items and plugins */ /* removed added items and plugins */
for ( ; pi-- != p->items; ) { for ( ; pi-- != p->items; ) {
g_hash_table_remove(ps->load_items, pi->name); g_hash_table_remove(ps->items, pi->name);
} }
g_ptr_array_set_size(ps->load_plugins, ps->load_plugins->len - i+1); g_ptr_array_set_size(ps->plugins, ps->plugins->len - i+1);
for ( ; i-- > 0; ) { for ( ; i-- > 0; ) {
p = g_ptr_array_index(sm->plugins, i); p = g_ptr_array_index(sm->plugins, i);
g_hash_table_remove(ps->load_ht_plugins, p->name); g_hash_table_remove(ps->ht_plugins, p->name);
if (!p->items) continue; if (!p->items) continue;
for (pi = p->items; pi->name; pi++) { for (pi = p->items; pi->name; pi++) {
g_hash_table_remove(ps->load_items, pi->name); g_hash_table_remove(ps->items, pi->name);
} }
} }
@ -275,16 +231,14 @@ gboolean li_plugins_load_module(liServer *srv, const gchar *name) {
server_module *sm; server_module *sm;
const gchar* modname = name ? name : "core"; const gchar* modname = name ? name : "core";
sm = g_hash_table_lookup(ps->load_module_refs, modname);
if (sm) return TRUE; /* already loaded */
sm = g_hash_table_lookup(ps->module_refs, modname); sm = g_hash_table_lookup(ps->module_refs, modname);
if (sm) { /* loaded in previous config */ if (sm) return TRUE; /* already loaded */
server_module_acquire(sm);
g_hash_table_insert(ps->load_module_refs, sm->name, sm); {
} else { /* not loaded yet */ /* not loaded yet */
liModule *mod; liModule *mod;
sm = server_module_new(srv, modname); sm = server_module_new(srv, modname);
g_hash_table_insert(ps->load_module_refs, sm->name, sm); g_hash_table_insert(ps->module_refs, sm->name, sm);
if (name) { if (name) {
mod = li_module_load(ps->modules, name); mod = li_module_load(ps->modules, name);
@ -315,7 +269,7 @@ liPlugin *li_angel_plugin_register(liServer *srv, liModule *mod, const gchar *na
liPlugin *p; liPlugin *p;
const gchar* modname = mod ? mod->name->str : "core"; const gchar* modname = mod ? mod->name->str : "core";
sm = g_hash_table_lookup(ps->load_module_refs, modname); sm = g_hash_table_lookup(ps->module_refs, modname);
if (!sm) { if (!sm) {
ERROR(srv, "Module '%s' not loaded; cannot load plugin '%s'", modname, name); ERROR(srv, "Module '%s' not loaded; cannot load plugin '%s'", modname, name);
return NULL; return NULL;

View File

@ -16,6 +16,69 @@ typedef struct listen_ref_resource listen_ref_resource;
# define DEFAULT_LIBEXECDIR "/usr/local/lib/lighttpd2" # define DEFAULT_LIBEXECDIR "/usr/local/lib/lighttpd2"
#endif #endif
struct plugin_parsing {
GPtrArray *env; /* <gchar*> */
GString *user;
uid_t user_uid;
gid_t user_gid;
GString *group;
gid_t group_gid;
GString *binary;
GString *config;
GString *luaconfig;
GString *modules_path;
GPtrArray *wrapper; /* <gchar*> */
gint64 rlim_core, rlim_nofile;
liInstanceConf *instconf;
GPtrArray *listen_masks;
};
typedef struct plugin_config plugin_config;
struct plugin_config {
/* Parsing/Load */
struct plugin_parsing parsing;
/* Running */
liInstanceConf *instconf;
GPtrArray *listen_masks;
liInstance *inst;
GHashTable *listen_sockets;
liEventSignal sig_hup;
};
typedef struct listen_mask listen_mask;
struct listen_mask {
enum {
LI_PLUGIN_CORE_LISTEN_MASK_IPV4,
LI_PLUGIN_CORE_LISTEN_MASK_IPV6,
LI_PLUGIN_CORE_LISTEN_MASK_UNIX
} type;
union {
struct {
guint32 addr;
guint32 networkmask;
guint16 port;
} ipv4;
struct {
guint8 addr[16];
guint network;
guint16 port;
} ipv6;
struct {
GString *path;
} unix_socket;
} value;
};
struct listen_socket { struct listen_socket {
gint refcount; gint refcount;
@ -89,7 +152,7 @@ static gboolean core_parse_store_integer(liValue *value, const char* item, gint6
static gboolean core_parse_user(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_user(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
struct passwd *pwd; struct passwd *pwd;
GString *user; GString *user;
UNUSED(srv); UNUSED(srv);
@ -120,7 +183,7 @@ static gboolean core_parse_user(liServer *srv, liPlugin *p, liValue *value, GErr
} }
static gboolean core_parse_group(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_group(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
struct group *grp; struct group *grp;
GString *group; GString *group;
UNUSED(srv); UNUSED(srv);
@ -145,14 +208,14 @@ static gboolean core_parse_group(liServer *srv, liPlugin *p, liValue *value, GEr
} }
static gboolean core_parse_binary(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_binary(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
return core_parse_store_string(value, "binary", &pc->parsing.binary, err); return core_parse_store_string(value, "binary", &pc->parsing.binary, err);
} }
static gboolean core_parse_config(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_config(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
if (NULL != pc->parsing.luaconfig) { if (NULL != pc->parsing.luaconfig) {
@ -165,7 +228,7 @@ static gboolean core_parse_config(liServer *srv, liPlugin *p, liValue *value, GE
} }
static gboolean core_parse_luaconfig(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_luaconfig(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
if (NULL != pc->parsing.config) { if (NULL != pc->parsing.config) {
@ -178,7 +241,7 @@ static gboolean core_parse_luaconfig(liServer *srv, liPlugin *p, liValue *value,
} }
static gboolean core_parse_modules_path(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_modules_path(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
return core_parse_store_string(value, "modules_path", &pc->parsing.modules_path, err); return core_parse_store_string(value, "modules_path", &pc->parsing.modules_path, err);
@ -194,7 +257,7 @@ static void add_env(GPtrArray *env, const char *key, size_t keylen, const char *
} }
static gboolean core_parse_env(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_env(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
value = li_value_get_single_argument(value); value = li_value_get_single_argument(value);
@ -226,7 +289,7 @@ parameter_type_error:
} }
static gboolean core_parse_copy_env(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_copy_env(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
value = li_value_get_single_argument(value); value = li_value_get_single_argument(value);
@ -256,14 +319,14 @@ parameter_type_error:
} }
static gboolean core_parse_wrapper(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_wrapper(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
return core_parse_store_string_list(value, "wrapper", pc->parsing.wrapper, err); return core_parse_store_string_list(value, "wrapper", pc->parsing.wrapper, err);
} }
static gboolean core_parse_max_core_file_size(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_max_core_file_size(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
if (-1 != pc->parsing.rlim_core) { if (-1 != pc->parsing.rlim_core) {
@ -276,7 +339,7 @@ static gboolean core_parse_max_core_file_size(liServer *srv, liPlugin *p, liValu
} }
static gboolean core_parse_max_open_files(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_max_open_files(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
if (-1 != pc->parsing.rlim_nofile) { if (-1 != pc->parsing.rlim_nofile) {
@ -291,7 +354,7 @@ static gboolean core_parse_max_open_files(liServer *srv, liPlugin *p, liValue *v
static void core_listen_mask_free(liPluginCoreListenMask *mask) { static void core_listen_mask_free(listen_mask *mask) {
if (NULL == mask) return; if (NULL == mask) return;
switch (mask->type) { switch (mask->type) {
@ -302,11 +365,11 @@ static void core_listen_mask_free(liPluginCoreListenMask *mask) {
g_string_free(mask->value.unix_socket.path, TRUE); g_string_free(mask->value.unix_socket.path, TRUE);
break; break;
} }
g_slice_free(liPluginCoreListenMask, mask); g_slice_free(listen_mask, mask);
} }
static gboolean core_parse_allow_listen(liServer *srv, liPlugin *p, liValue *value, GError **err) { static gboolean core_parse_allow_listen(liServer *srv, liPlugin *p, liValue *value, GError **err) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
value = li_value_get_single_argument(value); value = li_value_get_single_argument(value);
@ -316,12 +379,12 @@ static gboolean core_parse_allow_listen(liServer *srv, liPlugin *p, liValue *val
LI_VALUE_FOREACH(entry, value) LI_VALUE_FOREACH(entry, value)
GString *s; GString *s;
liPluginCoreListenMask *mask; listen_mask *mask;
if (LI_VALUE_STRING != li_value_type(entry)) goto parameter_type_error; if (LI_VALUE_STRING != li_value_type(entry)) goto parameter_type_error;
s = entry->data.string; s = entry->data.string;
mask = g_slice_new0(liPluginCoreListenMask); mask = g_slice_new0(listen_mask);
if (li_string_prefix(s, CONST_STR_LEN("unix:/"))) { if (li_string_prefix(s, CONST_STR_LEN("unix:/"))) {
mask->type = LI_PLUGIN_CORE_LISTEN_MASK_UNIX; mask->type = LI_PLUGIN_CORE_LISTEN_MASK_UNIX;
mask->value.unix_socket.path = li_value_extract_string(entry); mask->value.unix_socket.path = li_value_extract_string(entry);
@ -336,7 +399,7 @@ static gboolean core_parse_allow_listen(liServer *srv, liPlugin *p, liValue *val
else { else {
g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE, g_set_error(err, LI_ANGEL_CONFIG_PARSER_ERROR, LI_ANGEL_CONFIG_PARSER_ERROR_PARSE,
"allow_listen: couldn't parse socket address mask '%s'", s->str); "allow_listen: couldn't parse socket address mask '%s'", s->str);
g_slice_free(liPluginCoreListenMask, mask); g_slice_free(listen_mask, mask);
return FALSE; return FALSE;
} }
@ -386,7 +449,7 @@ static const liPluginItem core_items[] = {
} }
static void core_parse_init(liServer *srv, liPlugin *p) { static void core_parse_init(liServer *srv, liPlugin *p) {
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
UNUSED(srv); UNUSED(srv);
INIT_STR_LIST(env); INIT_STR_LIST(env);
@ -427,7 +490,7 @@ static gboolean core_check(liServer *srv, liPlugin *p, GError **err) {
GPtrArray *cmd; GPtrArray *cmd;
GString *user; GString *user;
gchar **cmdarr, **envarr; gchar **cmdarr, **envarr;
liPluginCoreConfig *pc = p->data; plugin_config *pc = p->data;
gid_t gid = ((gid_t)-1 != pc->parsing.group_gid) ? pc->parsing.group_gid : pc->parsing.user_gid; gid_t gid = ((gid_t)-1 != pc->parsing.group_gid) ? pc->parsing.group_gid : pc->parsing.user_gid;
UNUSED(srv); UNUSED(srv);
UNUSED(err); UNUSED(err);
@ -500,7 +563,7 @@ static void listen_ref_release(liServer *srv, liInstance *i, liPlugin *p, liInst
LI_FORCE_ASSERT(g_atomic_int_get(&sock->refcount) > 0); LI_FORCE_ASSERT(g_atomic_int_get(&sock->refcount) > 0);
if (g_atomic_int_dec_and_test(&sock->refcount)) { if (g_atomic_int_dec_and_test(&sock->refcount)) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data; plugin_config *config = (plugin_config*) p->data;
/* theoretically the hash table entry might not point to `sock`, /* theoretically the hash table entry might not point to `sock`,
* but a) that shouldn't happen (can't bind two sockets to same * but a) that shouldn't happen (can't bind two sockets to same
@ -527,9 +590,9 @@ static void listen_socket_add(liInstance *i, liPlugin *p, listen_socket *sock) {
li_instance_add_resource(i, &ref->ires, listen_ref_release, p, ref); li_instance_add_resource(i, &ref->ires, listen_ref_release, p, ref);
} }
static gboolean listen_check_acl(liServer *srv, liPluginCoreConfig *config, liSocketAddress *addr) { static gboolean listen_check_acl(liServer *srv, plugin_config *config, liSocketAddress *addr) {
guint i; guint i;
liPluginCoreListenMask *mask; listen_mask *mask;
switch (addr->addr_up.plain->sa_family) { switch (addr->addr_up.plain->sa_family) {
case AF_INET: { case AF_INET: {
@ -720,7 +783,7 @@ static void core_listen(liServer *srv, liPlugin *p, liInstance *i, gint32 id, GS
GError *err = NULL; GError *err = NULL;
gint fd; gint fd;
GArray *fds; GArray *fds;
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data; plugin_config *config = (plugin_config*) p->data;
liSocketAddress addr; liSocketAddress addr;
listen_socket *sock; listen_socket *sock;
@ -866,7 +929,7 @@ static void core_log_open_file(liServer *srv, liPlugin *p, liInstance *i, gint32
} }
static void core_free(liServer *srv, liPlugin *p) { static void core_free(liServer *srv, liPlugin *p) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data; plugin_config *config = (plugin_config*) p->data;
guint i; guint i;
li_event_clear(&config->sig_hup); li_event_clear(&config->sig_hup);
@ -897,11 +960,22 @@ static void core_free(liServer *srv, liPlugin *p) {
g_hash_table_destroy(config->listen_sockets); g_hash_table_destroy(config->listen_sockets);
config->listen_masks = NULL; config->listen_masks = NULL;
g_slice_free(liPluginCoreConfig, config); g_slice_free(plugin_config, config);
}
static void core_stop(liServer *srv, liPlugin *p) {
plugin_config *config = (plugin_config *)p->data;
UNUSED(srv);
if (config->inst) {
li_instance_set_state(config->inst, LI_INSTANCE_FINISHED);
li_instance_release(config->inst);
config->inst = NULL;
}
} }
static void core_activate(liServer *srv, liPlugin *p) { static void core_activate(liServer *srv, liPlugin *p) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data; plugin_config *config = (plugin_config*) p->data;
GPtrArray *tmp_ptrarray; GPtrArray *tmp_ptrarray;
guint i; guint i;
@ -934,7 +1008,7 @@ static void core_activate(liServer *srv, liPlugin *p) {
} }
static void core_instance_replaced(liServer *srv, liPlugin *p, liInstance *oldi, liInstance *newi) { static void core_instance_replaced(liServer *srv, liPlugin *p, liInstance *oldi, liInstance *newi) {
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data; plugin_config *config = (plugin_config*) p->data;
UNUSED(srv); UNUSED(srv);
if (oldi == config->inst && LI_INSTANCE_FINISHED == oldi->s_cur) { if (oldi == config->inst && LI_INSTANCE_FINISHED == oldi->s_cur) {
@ -945,7 +1019,7 @@ static void core_instance_replaced(liServer *srv, liPlugin *p, liInstance *oldi,
} }
static void core_handle_sig_hup(liEventBase *watcher, int events) { static void core_handle_sig_hup(liEventBase *watcher, int events) {
liPluginCoreConfig *config = LI_CONTAINER_OF(li_event_signal_from(watcher), liPluginCoreConfig, sig_hup); plugin_config *config = LI_CONTAINER_OF(li_event_signal_from(watcher), plugin_config, sig_hup);
liInstance *oldi, *newi; liInstance *oldi, *newi;
UNUSED(events); UNUSED(events);
@ -960,13 +1034,13 @@ static void core_handle_sig_hup(liEventBase *watcher, int events) {
} }
static gboolean core_init(liServer *srv, liPlugin *p) { static gboolean core_init(liServer *srv, liPlugin *p) {
liPluginCoreConfig *config; plugin_config *config;
UNUSED(srv); UNUSED(srv);
p->data = config = g_slice_new0(liPluginCoreConfig); p->data = config = g_slice_new0(plugin_config);
p->items = core_items; p->items = core_items;
p->handle_free = core_free; p->handle_free = core_free;
p->handle_clean_config = core_parse_init; p->handle_stop = core_stop;
p->handle_check_config = core_check; p->handle_check_config = core_check;
p->handle_activate_config = core_activate; p->handle_activate_config = core_activate;
p->handle_instance_replaced = core_instance_replaced; p->handle_instance_replaced = core_instance_replaced;

View File

@ -46,7 +46,7 @@ void li_server_stop(liServer *srv) {
li_event_stop(&srv->sig_w_INT); li_event_stop(&srv->sig_w_INT);
li_event_stop(&srv->sig_w_TERM); li_event_stop(&srv->sig_w_TERM);
li_plugins_config_load(srv, NULL); li_plugins_stop(srv);
li_event_loop_end(&srv->loop); li_event_loop_end(&srv->loop);
} }
@ -125,24 +125,24 @@ static void instance_child_cb(liEventBase *watcher, int events) {
if (i->s_dest == LI_INSTANCE_FINISHED) { if (i->s_dest == LI_INSTANCE_FINISHED) {
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
if (0 != WEXITSTATUS(status)) { if (0 != WEXITSTATUS(status)) {
ERROR(i->srv, "child %i died with exit status %i", i->proc->child_pid, WEXITSTATUS(status)); ERROR(i->srv, "instance[%i] died with exit status %i", i->pid, WEXITSTATUS(status));
} /* exit status 0 is ok, no message */ } /* exit status 0 is ok, no message */
} else if (WIFSIGNALED(status)) { } else if (WIFSIGNALED(status)) {
ERROR(i->srv, "child %i died: killed by '%s' (%i)", i->proc->child_pid, g_strsignal(WTERMSIG(status)), WTERMSIG(status)); ERROR(i->srv, "instance[%i] died: killed by '%s' (%i)", i->pid, g_strsignal(WTERMSIG(status)), WTERMSIG(status));
} else { } else {
ERROR(i->srv, "child %i died with unexpected stat_val %i", i->proc->child_pid, status); ERROR(i->srv, "instance[%i] died with unexpected stat_val %i", i->pid, status);
} }
news = LI_INSTANCE_FINISHED; news = LI_INSTANCE_FINISHED;
} else { } else {
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
ERROR(i->srv, "child %i died with exit status %i", i->proc->child_pid, WEXITSTATUS(status)); ERROR(i->srv, "instance[%i] died with exit status %i", i->pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) { } else if (WIFSIGNALED(status)) {
ERROR(i->srv, "child %i died: killed by %s", i->proc->child_pid, g_strsignal(WTERMSIG(status))); ERROR(i->srv, "instance[%i] died: killed by %s", i->pid, g_strsignal(WTERMSIG(status)));
} else { } else {
ERROR(i->srv, "child %i died with unexpected stat_val %i", i->proc->child_pid, status); ERROR(i->srv, "instance[%i] died with unexpected stat_val %i", i->pid, status);
} }
if (i->s_cur == LI_INSTANCE_DOWN) { if (i->s_cur == LI_INSTANCE_DOWN) {
ERROR(i->srv, "spawning child %i failed, not restarting", i->proc->child_pid); ERROR(i->srv, "instance[%i] spawning failed, not restarting", i->pid);
news = i->s_dest = LI_INSTANCE_FINISHED; /* TODO: retry spawn later? */ news = i->s_dest = LI_INSTANCE_FINISHED; /* TODO: retry spawn later? */
} else { } else {
news = LI_INSTANCE_DOWN; news = LI_INSTANCE_DOWN;
@ -183,12 +183,13 @@ static void instance_spawn(liInstance *i) {
if (!i->proc) return; if (!i->proc) return;
i->pid = i->proc->child_pid;
close(confd[1]); close(confd[1]);
li_event_clear(&i->child_watcher); li_event_clear(&i->child_watcher);
li_event_child_init(&i->srv->loop, "lighttpd2-worker", &i->child_watcher, instance_child_cb, i->proc->child_pid); li_event_child_init(&i->srv->loop, "lighttpd2-worker", &i->child_watcher, instance_child_cb, i->proc->child_pid);
i->s_cur = LI_INSTANCE_DOWN; i->s_cur = LI_INSTANCE_DOWN;
li_instance_acquire(i); li_instance_acquire(i);
DEBUG(i->srv, "Instance (%i) spawned: %s", i->proc->child_pid, i->ic->cmd[0]); INFO(i->srv, "instance[%i] spawned: %s", i->pid, i->ic->cmd[0]);
} }
liInstance* li_server_new_instance(liServer *srv, liInstanceConf *ic) { liInstance* li_server_new_instance(liServer *srv, liInstanceConf *ic) {
@ -335,7 +336,7 @@ void li_instance_state_reached(liInstance *i, liInstanceState s) {
li_instance_unset_replace(i->replace, i); li_instance_unset_replace(i->replace, i);
} else if (i->s_dest == LI_INSTANCE_FINISHED) { } else if (i->s_dest == LI_INSTANCE_FINISHED) {
if (i->replace_by) { if (i->replace_by) {
INFO(i->srv, "%s", "Instance replaced"); INFO(i->srv, "instance[%i] replaced by instance[%i]", i->pid, i->replace_by->pid);
if (i->replace_by->s_dest == LI_INSTANCE_WARMUP) { if (i->replace_by->s_dest == LI_INSTANCE_WARMUP) {
li_instance_set_state(i->replace_by, LI_INSTANCE_RUNNING); li_instance_set_state(i->replace_by, LI_INSTANCE_RUNNING);
} }
@ -371,7 +372,7 @@ void li_instance_release(liInstance *i) {
if (!g_atomic_int_dec_and_test(&i->refcount)) return; if (!g_atomic_int_dec_and_test(&i->refcount)) return;
g_assert(!i->proc); g_assert(!i->proc);
DEBUG(srv, "%s", "instance released"); DEBUG(srv, "instance[%i] released", i->pid);
li_instance_conf_release(i->ic); li_instance_conf_release(i->ic);
i->ic = NULL; i->ic = NULL;

View File

@ -712,11 +712,6 @@ static void li_server_start_transition(liServer *srv, liServerState state) {
/* wait for closed connections and plugins */ /* wait for closed connections and plugins */
break; break;
case LI_SERVER_STOPPING: case LI_SERVER_STOPPING:
{
liAction* mainaction = srv->mainaction;
srv->mainaction = NULL;
li_action_release(srv, mainaction);
}
/* stop all workers */ /* stop all workers */
for (i = 0; i < srv->worker_count; i++) { for (i = 0; i < srv->worker_count; i++) {
liWorker *wrk; liWorker *wrk;