From 3d3d0304bc1cd919f97d061f79f04a4e2ab974b1 Mon Sep 17 00:00:00 2001 From: "roberto@mrspurr" Date: Sat, 7 May 2011 09:21:07 +0200 Subject: [PATCH] plugin autoloading (finally) --- buildconf/default.ini | 2 +- plugins.c | 49 +++++++++++++++++++++++++++++++++---------- uwsgi.c | 34 ++++++++++++++++++++++++++++++ uwsgi.h | 5 ++++- 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/buildconf/default.ini b/buildconf/default.ini index c5ea9a95..da55285d 100644 --- a/buildconf/default.ini +++ b/buildconf/default.ini @@ -4,7 +4,7 @@ ini = true yaml = true json = auto sqlite3 = auto -zeromq = auto +zeromq = false snmp = true sctp = false spooler = true diff --git a/plugins.c b/plugins.c index 63c4f7cf..b91c708e 100644 --- a/plugins.c +++ b/plugins.c @@ -2,7 +2,7 @@ extern struct uwsgi_server uwsgi; -int uwsgi_load_plugin(int modifier, char *plugin, char *pargs, int absolute) { +void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) { void *plugin_handle; @@ -23,7 +23,7 @@ check: #ifdef UWSGI_DEBUG uwsgi_log("%s plugin already available\n", plugin); #endif - return 0; + return NULL; } } if (uwsgi.p[i]->alias) { @@ -31,7 +31,7 @@ check: #ifdef UWSGI_DEBUG uwsgi_log("%s plugin already available\n", plugin); #endif - return 0; + return NULL; } } } @@ -43,7 +43,7 @@ check: #ifdef UWSGI_DEBUG uwsgi_log("%s plugin already available\n", plugin); #endif - return 0; + return NULL; } } if (uwsgi.gp[i]->alias) { @@ -51,7 +51,7 @@ check: #ifdef UWSGI_DEBUG uwsgi_log("%s plugin already available\n", plugin); #endif - return 0; + return NULL; } } } @@ -63,12 +63,18 @@ check: goto check; } - if (absolute) { - plugin_name = malloc(strlen(plugin) + 1); - memcpy(plugin_name, plugin, strlen(plugin) + 1); + if (absolute == 1) { + plugin_name = uwsgi_concat2(plugin, ""); + // need to fix this... postpone until needed + plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0); } + else if (absolute == 2) { + plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin); + plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0); + } else { plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so"); + plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin"); } plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL); free(plugin_name); @@ -77,19 +83,40 @@ check: uwsgi_log( "%s\n", dlerror()); } else { - plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin"); up = dlsym(plugin_handle, plugin_entry_symbol); if (up) { + if (has_option) { + struct option *lopt = up->options, *aopt; + int found = 0; + while ((aopt = lopt)) { + if (!aopt->name) + break; + if (!strcmp(has_option, aopt->name)) { + found = 1; + break; + } + lopt++; + } + if (!found) { + if (dlclose(plugin_handle)) { + uwsgi_error("dlclose()"); + } + free(plugin_entry_symbol); + return NULL; + } + + } if (modifier != -1) { fill_plugin_table(modifier, up); } else { fill_plugin_table(up->modifier1, up); } - return 1; + free(plugin_entry_symbol); + return plugin_handle; } uwsgi_log( "%s\n", dlerror()); } - return 0; + return NULL; } diff --git a/uwsgi.c b/uwsgi.c index f32d2beb..b0a0d47d 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -198,6 +198,7 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = { {"worker-exec", required_argument, 0, LONG_ARGS_WORKER_EXEC}, {"attach-daemon", required_argument, 0, LONG_ARGS_ATTACH_DAEMON}, {"plugins", required_argument, 0, LONG_ARGS_PLUGINS}, + {"autoload", no_argument, &uwsgi.autoload, 1}, {"allowed-modifiers", required_argument, 0, LONG_ARGS_ALLOWED_MODIFIERS}, {"remap-modifier", required_argument, 0, LONG_ARGS_REMAP_MODIFIER}, {"dump-options", no_argument, &uwsgi.dump_options, 1}, @@ -213,17 +214,24 @@ void uwsgi_configure(void) { struct option *aopt; char *val; int i; + int is_retry; + int found; for (i = 0; i < uwsgi.exported_opts_cnt; i++) { if (uwsgi.exported_opts[i]->configured) continue; + + is_retry = 0; +retry: + found = 0; lopt = uwsgi.long_options;; while ((aopt = lopt)) { if (!aopt->name) break; if (!strcmp(aopt->name, uwsgi.exported_opts[i]->key)) { + found = 1; val = uwsgi.exported_opts[i]->value; if (aopt->flag) @@ -245,6 +253,32 @@ void uwsgi_configure(void) { } lopt++; } + + if (!found && uwsgi.autoload && !is_retry) { + DIR *pdir; + struct dirent *dp; + pdir = opendir(UWSGI_PLUGIN_DIR); + if (!pdir) { + uwsgi_fatal_error("opendir()"); + } + while ((dp = readdir(pdir)) != NULL) { + if (!strncmp("_plugin.so", dp->d_name+(strlen(dp->d_name)-10), 19)) { + if (uwsgi_load_plugin(-1, dp->d_name, uwsgi.exported_opts[i]->key, 2)) { + uwsgi_log("option \"%s\" found in plugin %s\n", uwsgi.exported_opts[i]->key, dp->d_name); + found = 1; + break; + } + } + } + if (found) { + build_options(); + closedir(pdir); + // avoid deadly loops... + is_retry = 1; + goto retry; + } + closedir(pdir); + } } } diff --git a/uwsgi.h b/uwsgi.h index 686d58fd..5ad8164b 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -7,6 +7,7 @@ #define UMAX16 65536 #define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); +#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1); #define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__); #define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__); #define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()") @@ -842,6 +843,8 @@ struct uwsgi_server { int apps_cnt; int default_app; + int autoload; + unsigned int reloads; int master_as_root; @@ -1509,7 +1512,7 @@ void uwsgi_log(const char *,...); void uwsgi_log_verbose(const char *,...); -int uwsgi_load_plugin(int, char *, char *, int); +void *uwsgi_load_plugin(int, char *, char *, int); int unconfigured_hook(struct wsgi_request *);