diff options
author | Martin Willi <martin@revosec.ch> | 2013-05-03 16:24:05 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-07-18 12:17:54 +0200 |
commit | 3dcc9d7aa72d391dc73d79d48ef1279c7228a85c (patch) | |
tree | a1f82c67cc68c7aa3e2bbcf38f472c311e6e26be /src/frontends/osx/charon-xpc/charon-xpc.c | |
parent | 4204d1d71a9495f57acc37aeeb913fdd5828408f (diff) | |
download | strongswan-3dcc9d7aa72d391dc73d79d48ef1279c7228a85c.tar.bz2 strongswan-3dcc9d7aa72d391dc73d79d48ef1279c7228a85c.tar.xz |
xpc: move dispatching to dedicated class, using dedicated thread
Diffstat (limited to 'src/frontends/osx/charon-xpc/charon-xpc.c')
-rw-r--r-- | src/frontends/osx/charon-xpc/charon-xpc.c | 174 |
1 files changed, 88 insertions, 86 deletions
diff --git a/src/frontends/osx/charon-xpc/charon-xpc.c b/src/frontends/osx/charon-xpc/charon-xpc.c index 19142d894..477e1e0c4 100644 --- a/src/frontends/osx/charon-xpc/charon-xpc.c +++ b/src/frontends/osx/charon-xpc/charon-xpc.c @@ -17,11 +17,29 @@ #include <sys/utsname.h> #include <unistd.h> #include <stdio.h> -#include <xpc/xpc.h> +#include <signal.h> +#include <pthread.h> #include <library.h> #include <hydra.h> #include <daemon.h> +#include <threading/thread.h> +#include <utils/backtrace.h> + +#include "xpc_dispatch.h" + +/** + * XPC dispatcher class + */ +static xpc_dispatch_t *dispatcher; + +/** + * atexit() cleanup for dispatcher + */ +void dispatcher_cleanup() +{ + DESTROY_IF(dispatcher); +} /** * Loglevel configuration @@ -51,97 +69,57 @@ static void dbg_stderr(debug_t group, level_t level, char *fmt, ...) } /** - * Return version of this helper + * Run the daemon and handle unix signals */ -xpc_object_t get_version(xpc_object_t request, xpc_connection_t client) +static int run() { - xpc_object_t reply; + sigset_t set; - reply = xpc_dictionary_create_reply(request); - xpc_dictionary_set_string(reply, "version", PACKAGE_VERSION); - - return reply; -} + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigprocmask(SIG_BLOCK, &set, NULL); -/** - * XPC command dispatch table - */ -struct { - char *name; - xpc_object_t (*handler)(xpc_object_t request, xpc_connection_t client); -} commands[] = { - { "get_version", get_version }, -}; + while (TRUE) + { + int sig; -/** - * Handle a received XPC request message - */ -static void handle(xpc_object_t request) -{ - xpc_connection_t client; - xpc_object_t reply; - const char *command; - int i; - - client = xpc_dictionary_get_remote_connection(request); - command = xpc_dictionary_get_string(request, "command"); - if (command) - { - for (i = 0; i < countof(commands); i++) - { - if (streq(commands[i].name, command)) - { - reply = commands[i].handler(request, client); - if (reply) - { - xpc_connection_send_message(client, reply); - xpc_release(reply); - } - break; - } - } - } + if (sigwait(&set, &sig)) + { + DBG1(DBG_DMN, "error while waiting for a signal"); + return 1; + } + switch (sig) + { + case SIGINT: + DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down"); + charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); + return 0; + case SIGTERM: + DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down"); + charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); + return 0; + default: + DBG1(DBG_DMN, "unknown signal %d received. Ignored", sig); + break; + } + } } /** - * Dispatch XPC commands + * Handle SIGSEGV/SIGILL signals raised by threads */ -static int dispatch() +static void segv_handler(int signal) { - xpc_connection_t service; - - service = xpc_connection_create_mach_service("org.strongswan.charon-xpc", - NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER); - if (!service) - { - return EXIT_FAILURE; - } - - xpc_connection_set_event_handler(service, ^(xpc_object_t conn) { - - xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { - - if (xpc_get_type(event) == XPC_TYPE_ERROR) - { - if (event == XPC_ERROR_CONNECTION_INVALID || - event == XPC_ERROR_TERMINATION_IMMINENT) - { - xpc_connection_cancel(conn); - } - } - else - { - handle(event); - } - }); - xpc_connection_resume(conn); - }); - - xpc_connection_resume(service); - - dispatch_main(); - - xpc_release(service); + backtrace_t *backtrace; + + DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal); + backtrace = backtrace_create(2); + backtrace->log(backtrace, NULL, TRUE); + backtrace->destroy(backtrace); + + DBG1(DBG_DMN, "killing ourself, received critical signal"); + abort(); } /** @@ -149,6 +127,7 @@ static int dispatch() */ int main(int argc, char *argv[]) { + struct sigaction action; struct utsname utsname; int group; @@ -184,9 +163,9 @@ int main(int argc, char *argv[]) lib->settings->set_default_str(lib->settings, "charon-cmd.port", "0"); lib->settings->set_default_str(lib->settings, "charon-cmd.port_nat_t", "0"); if (!charon->initialize(charon, - lib->settings->get_str(lib->settings, "charon-xpc.load", - "random nonce pem pkcs1 openssl kernel-pfkey kernel-pfroute " - "socket-default eap-identity eap-mschapv2"))) + lib->settings->get_str(lib->settings, "charon-xpc.load", + "random nonce pem pkcs1 openssl kernel-pfkey kernel-pfroute " + "socket-default eap-identity eap-mschapv2"))) { exit(SS_RC_INITIALIZATION_FAILED); } @@ -198,6 +177,29 @@ int main(int argc, char *argv[]) DBG1(DBG_DMN, "Starting charon-xpc IKE daemon (strongSwan %s, %s %s, %s)", VERSION, utsname.sysname, utsname.release, utsname.machine); + /* add handler for SEGV and ILL, + * INT, TERM and HUP are handled by sigwait() in run() */ + action.sa_handler = segv_handler; + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + sigaddset(&action.sa_mask, SIGINT); + sigaddset(&action.sa_mask, SIGTERM); + sigaddset(&action.sa_mask, SIGHUP); + sigaction(SIGSEGV, &action, NULL); + sigaction(SIGILL, &action, NULL); + sigaction(SIGBUS, &action, NULL); + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + + pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); + + dispatcher = xpc_dispatch_create(); + if (!dispatcher) + { + exit(SS_RC_INITIALIZATION_FAILED); + } + atexit(dispatcher_cleanup); + charon->start(charon); - return dispatch(); + return run(); } |