Signed-off-by: Victor Westerhuis <vic...@westerhu.is> --- debuginfod/debuginfod.cxx | 161 ++++++++++++++++++++++++++++---------- 1 file changed, 121 insertions(+), 40 deletions(-)
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index 2aecc049..caced48c 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -93,6 +93,10 @@ using namespace std; #include <microhttpd.h> +#ifdef ENABLE_SYSTEMD +#include <systemd/sd-daemon.h> +#endif + #if MHD_VERSION >= 0x00097002 // libmicrohttpd 0.9.71 broke API #define MHD_RESULT enum MHD_Result @@ -367,6 +371,10 @@ static const struct argp_option options[] = { "fdcache-prefetch", ARGP_KEY_FDCACHE_PREFETCH, "NUM", 0, "Number of archive files to prefetch into fdcache.", 0 }, #define ARGP_KEY_FDCACHE_MINTMP 0x1004 { "fdcache-mintmp", ARGP_KEY_FDCACHE_MINTMP, "NUM", 0, "Minimum free space% on tmpdir.", 0 }, +#ifdef ENABLE_SYSTEMD +#define ARGP_KEY_SYSTEMD 0x1005 + { "systemd", ARGP_KEY_SYSTEMD, NULL, 0, "Use systemd socket activation and cache directory.", 0 }, +#endif { NULL, 0, NULL, 0, NULL, 0 } }; @@ -412,6 +420,9 @@ static long fdcache_mbs; static long fdcache_prefetch; static long fdcache_mintmp; static string tmpdir; +#ifdef ENABLE_SYSTEMD +static bool systemd; +#endif static void set_metric(const string& key, double value); // static void inc_metric(const string& key); @@ -541,6 +552,11 @@ parse_opt (int key, char *arg, case ARGP_KEY_ARG: source_paths.insert(string(arg)); break; +#ifdef ENABLE_SYSTEMD + case ARGP_KEY_SYSTEMD: + systemd = true; + break; +#endif // case 'h': argp_state_help (state, stderr, ARGP_HELP_LONG|ARGP_HELP_EXIT_OK); default: return ARGP_ERR_UNKNOWN; } @@ -3267,6 +3283,16 @@ static void sqlite3_sharedprefix_fn (sqlite3_context* c, int argc, sqlite3_value } +static void close_databases () +{ + sqlite3 *database = db; + sqlite3 *databaseq = dbq; + db = dbq = 0; // for signal_handler not to freak + (void) sqlite3_close (databaseq); + (void) sqlite3_close (database); +} + + int main (int argc, char *argv[]) { @@ -3372,46 +3398,105 @@ main (int argc, char *argv[]) "cannot run database schema ddl: %s", sqlite3_errmsg(db)); } - // Start httpd server threads. Separate pool for IPv4 and IPv6, in - // case the host only has one protocol stack. - MHD_Daemon *d4 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION + vector<MHD_Daemon *> daemons; +#ifdef ENABLE_SYSTEMD + if (systemd) + { + int fds = sd_listen_fds (true); + if (fds <= 0) + { + close_databases (); + error (EXIT_FAILURE, -fds, "cannot get fds from systemd"); + } + + for (int i = 0; i < fds; ++i) + { + int fd = SD_LISTEN_FDS_START + i; + + rc = sd_is_socket_inet (fd, AF_UNSPEC, SOCK_STREAM, true, 0); + if (rc < 0) + { + close_databases (); + error (EXIT_FAILURE, -rc, "unable to determine fd type"); + } + else if (rc == 0) + { + close_databases (); + error (EXIT_FAILURE, 0, + "fd %d is not of the correct socket type", fd); + } + + MHD_Daemon *d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION #if MHD_VERSION >= 0x00095300 - | MHD_USE_INTERNAL_POLLING_THREAD + | MHD_USE_INTERNAL_POLLING_THREAD #else - | MHD_USE_SELECT_INTERNALLY + | MHD_USE_SELECT_INTERNALLY #endif - | MHD_USE_DEBUG, /* report errors to stderr */ - http_port, - NULL, NULL, /* default accept policy */ - handler_cb, NULL, /* handler callback */ - MHD_OPTION_END); - MHD_Daemon *d6 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION + | MHD_USE_DEBUG /* report errors to stderr */ + | MHD_USE_ITC, /* don't close socket on shutdown */ + 0, + NULL, NULL, /* default accept policy */ + handler_cb, NULL, /* handler callback */ + MHD_OPTION_LISTEN_SOCKET, + fd, + MHD_OPTION_END); + if (d == NULL) + { + close_databases (); + error (EXIT_FAILURE, 0, + "cannot start http server on fd %d", fd); + } + + obatched(clog) << "started http server on fd " << fd << endl; + + daemons.push_back (d); + } + } + else +#endif + { + // Start httpd server threads. Separate pool for IPv4 and IPv6, in + // case the host only has one protocol stack. + MHD_Daemon *d4 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION #if MHD_VERSION >= 0x00095300 - | MHD_USE_INTERNAL_POLLING_THREAD + | MHD_USE_INTERNAL_POLLING_THREAD #else - | MHD_USE_SELECT_INTERNALLY + | MHD_USE_SELECT_INTERNALLY #endif - | MHD_USE_IPv6 - | MHD_USE_DEBUG, /* report errors to stderr */ - http_port, - NULL, NULL, /* default accept policy */ - handler_cb, NULL, /* handler callback */ - MHD_OPTION_END); - - if (d4 == NULL && d6 == NULL) // neither ipv4 nor ipv6? boo - { - sqlite3 *database = db; - sqlite3 *databaseq = dbq; - db = dbq = 0; // for signal_handler not to freak - sqlite3_close (databaseq); - sqlite3_close (database); - error (EXIT_FAILURE, 0, "cannot start http server at port %d", http_port); - } + | MHD_USE_DEBUG, /* report errors to stderr */ + http_port, + NULL, NULL, /* default accept policy */ + handler_cb, NULL, /* handler callback */ + MHD_OPTION_END); + MHD_Daemon *d6 = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION +#if MHD_VERSION >= 0x00095300 + | MHD_USE_INTERNAL_POLLING_THREAD +#else + | MHD_USE_SELECT_INTERNALLY +#endif + | MHD_USE_IPv6 + | MHD_USE_DEBUG, /* report errors to stderr */ + http_port, + NULL, NULL, /* default accept policy */ + handler_cb, NULL, /* handler callback */ + MHD_OPTION_END); + + if (d4 == NULL && d6 == NULL) // neither ipv4 nor ipv6? boo + { + close_databases (); + error (EXIT_FAILURE, 0, "cannot start http server at port %d", http_port); + } + + obatched(clog) << "started http server on " + << (d4 != NULL ? "IPv4 " : "") + << (d6 != NULL ? "IPv6 " : "") + << "port=" << http_port << endl; - obatched(clog) << "started http server on " - << (d4 != NULL ? "IPv4 " : "") - << (d6 != NULL ? "IPv6 " : "") - << "port=" << http_port << endl; + if (d4) + daemons.push_back(d4); + if (d6) + daemons.push_back(d6); + } // add maxigroom sql if -G given if (maxigroom) @@ -3505,8 +3590,8 @@ main (int argc, char *argv[]) pthread_join (it, NULL); /* Stop all the web service threads. */ - if (d4) MHD_stop_daemon (d4); - if (d6) MHD_stop_daemon (d6); + for (auto&& i : daemons) + MHD_stop_daemon (i); /* With all threads known dead, we can clean up the global resources. */ rc = sqlite3_exec (db, DEBUGINFOD_SQLITE_CLEANUP_DDL, NULL, NULL, NULL); @@ -3520,11 +3605,7 @@ main (int argc, char *argv[]) (void) regfree (& file_include_regex); (void) regfree (& file_exclude_regex); - sqlite3 *database = db; - sqlite3 *databaseq = dbq; - db = dbq = 0; // for signal_handler not to freak - (void) sqlite3_close (databaseq); - (void) sqlite3_close (database); + close_databases (); return 0; } -- 2.30.1