[RFC PATCH 2/6] Allow socket activation by systemd
Victor Westerhuis
victor@westerhu.is
Sun Mar 7 12:49:54 GMT 2021
Signed-off-by: Victor Westerhuis <victor@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
More information about the Elfutils-devel
mailing list