diff options
Diffstat (limited to 'scd/scdaemon.c')
-rw-r--r-- | scd/scdaemon.c | 230 |
1 files changed, 91 insertions, 139 deletions
diff --git a/scd/scdaemon.c b/scd/scdaemon.c index e26beba13..e8073b7ee 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -35,7 +35,7 @@ #endif /*HAVE_W32_SYSTEM*/ #include <unistd.h> #include <signal.h> -#include <pth.h> +#include <npth.h> #define JNLIB_NEED_LOG_LOGV #define JNLIB_NEED_AFLOCAL @@ -169,7 +169,7 @@ static ARGPARSE_OPTS opts[] = { easy way to block on card status changes it is the best we can do. For PC/SC we could in theory use an extra thread to wait for status changes but that requires a native thread because there is no way - to make the underlying PC/SC card change function block using a Pth + to make the underlying PC/SC card change function block using a Npth mechanism. Given that a native thread could only be used under W32 we don't do that at all. */ #define TIMERTICK_INTERVAL_SEC (0) @@ -206,20 +206,9 @@ static void *start_connection_thread (void *arg); static void handle_connections (int listen_fd); /* Pth wrapper function definitions. */ -ASSUAN_SYSTEM_PTH_IMPL; +ASSUAN_SYSTEM_NPTH_IMPL; -#if defined(GCRY_THREAD_OPTION_VERSION) && (GCRY_THREAD_OPTION_VERSION == 0) -#define USE_GCRY_THREAD_CBS 1 -#endif - -#ifdef USE_GCRY_THREAD_CBS -GCRY_THREAD_OPTION_PTH_IMPL; - -static int fixed_gcry_pth_init (void) -{ - return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0; -} -#endif +static int active_connections; static char * @@ -280,16 +269,16 @@ my_strusage (int level) static int tid_log_callback (unsigned long *rvalue) { -#ifdef PTH_HAVE_PTH_THREAD_ID - *rvalue = pth_thread_id (); -#else - *rvalue = (unsigned long)pth_self (); -#endif - return 2; /* Use use hex representation. */ -} - + int len = sizeof (*rvalue); + npth_t thread; + thread = npth_self (); + if (sizeof (thread) < len) + len = sizeof (thread); + memcpy (rvalue, &thread, len); + return 2; /* Use use hex representation. */ +} /* Setup the debugging. With a LEVEL of NULL only the active debug @@ -382,9 +371,6 @@ main (int argc, char **argv ) { ARGPARSE_ARGS pargs; int orig_argc; -#ifdef USE_GCRY_THREAD_CBS - gpg_error_t err; -#endif char **orig_argv; FILE *configfp = NULL; char *configname = NULL; @@ -406,6 +392,8 @@ main (int argc, char **argv ) int allow_coredump = 0; int standard_socket = 0; struct assuan_malloc_hooks malloc_hooks; + int res; + npth_t pipecon_handler; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -418,18 +406,7 @@ main (int argc, char **argv ) i18n_init (); init_common_subsystems (&argc, &argv); - - /* Libgcrypt requires us to register the threading model first. - Note that this will also do the pth_init. */ -#ifdef USE_GCRY_THREAD_CBS - gcry_threads_pth.init = fixed_gcry_pth_init; - err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); - if (err) - { - log_fatal ("can't register GNU Pth with Libgcrypt: %s\n", - gpg_strerror (err)); - } -#endif + npth_init (); /* Check that the libraries are suitable. Do it here because the option parsing may need services of the library */ @@ -446,7 +423,7 @@ main (int argc, char **argv ) malloc_hooks.free = gcry_free; assuan_set_malloc_hooks (&malloc_hooks); assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT); - assuan_set_system_hooks (ASSUAN_SYSTEM_PTH); + assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH); assuan_sock_init (); setup_libassuan_logging (&opt.debug); @@ -712,7 +689,7 @@ main (int argc, char **argv ) { /* This is the simple pipe based server */ ctrl_t ctrl; - pth_attr_t tattr; + npth_attr_t tattr; int fd = -1; #ifndef HAVE_W32_SYSTEM @@ -751,10 +728,14 @@ main (int argc, char **argv ) socket_name, &socket_nonce)); } - tattr = pth_attr_new(); - pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); - pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); - pth_attr_set (tattr, PTH_ATTR_NAME, "pipe-connection"); + res = npth_attr_init (&tattr); + if (res) + { + log_error ("error allocating thread attributes: %s\n", + strerror (res)); + scd_exit (2); + } + npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED); ctrl = xtrycalloc (1, sizeof *ctrl); if ( !ctrl ) @@ -764,13 +745,16 @@ main (int argc, char **argv ) scd_exit (2); } ctrl->thread_startup.fd = GNUPG_INVALID_FD; - if ( !pth_spawn (tattr, start_connection_thread, ctrl) ) + res = npth_create (&pipecon_handler, &tattr, start_connection_thread, ctrl); + if (res) { log_error ("error spawning pipe connection handler: %s\n", - strerror (errno) ); + strerror (res) ); xfree (ctrl); scd_exit (2); } + npth_setname_np (pipecon_handler, "pipe-connection"); + npth_attr_destroy (&tattr); /* We run handle_connection to wait for the shutdown signal and to run the ticker stuff. */ @@ -981,8 +965,8 @@ handle_signal (int signo) if (!shutdown_pending) log_info ("SIGTERM received - shutting down ...\n"); else - log_info ("SIGTERM received - still %ld running threads\n", - pth_ctrl( PTH_CTRL_GETTHREADS )); + log_info ("SIGTERM received - still %i running threads\n", + active_connections); shutdown_pending++; if (shutdown_pending > 2) { @@ -1176,9 +1160,7 @@ start_connection_thread (void *arg) static void handle_connections (int listen_fd) { - pth_attr_t tattr; - pth_event_t ev, time_ev; - sigset_t sigs; + npth_attr_t tattr; int signo; struct sockaddr_un paddr; socklen_t plen; @@ -1186,25 +1168,24 @@ handle_connections (int listen_fd) int ret; int fd; int nfd; + struct timespec abstime; + struct timespec curtime; + struct timespec timeout; + int saved_errno; - tattr = pth_attr_new(); - pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); - pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024); - -#ifndef HAVE_W32_SYSTEM /* fixme */ - sigemptyset (&sigs ); - sigaddset (&sigs, SIGHUP); - sigaddset (&sigs, SIGUSR1); - sigaddset (&sigs, SIGUSR2); - sigaddset (&sigs, SIGINT); - sigaddset (&sigs, SIGTERM); - pth_sigmask (SIG_UNBLOCK, &sigs, NULL); - ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); -#else - sigs = 0; - ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); + ret = npth_attr_init(&tattr); + /* FIXME: Check error. */ + npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED); + +#ifndef HAVE_W32_SYSTEM + npth_sigev_init (); + npth_sigev_add (SIGHUP); + npth_sigev_add (SIGUSR1); + npth_sigev_add (SIGUSR2); + npth_sigev_add (SIGINT); + npth_sigev_add (SIGTERM); + npth_sigev_fini (); #endif - time_ev = NULL; FD_ZERO (&fdset); nfd = 0; @@ -1214,13 +1195,17 @@ handle_connections (int listen_fd) nfd = listen_fd; } + npth_clock_gettime (&curtime); + timeout.tv_sec = TIMERTICK_INTERVAL_SEC; + timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000; + npth_timeradd (&curtime, &timeout, &abstime); + /* We only require abstime here. The others will be reused. */ + for (;;) { - sigset_t oldsigs; - if (shutdown_pending) { - if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1) + if (active_connections == 0) break; /* ready */ /* Do not accept anymore connections but wait for existing @@ -1231,80 +1216,50 @@ handle_connections (int listen_fd) listen_fd = -1; } - /* Create a timeout event if needed. Round it up to the next - microsecond interval to help with power saving. */ - if (!time_ev) - { - pth_time_t nexttick = pth_timeout (TIMERTICK_INTERVAL_SEC, - TIMERTICK_INTERVAL_USEC/2); - if ((nexttick.tv_usec % (TIMERTICK_INTERVAL_USEC/2)) > 10) - { - nexttick.tv_usec = ((nexttick.tv_usec - /(TIMERTICK_INTERVAL_USEC/2)) - + 1) * (TIMERTICK_INTERVAL_USEC/2); - if (nexttick.tv_usec >= 1000000) - { - nexttick.tv_sec++; - nexttick.tv_usec = 0; - } - } - time_ev = pth_event (PTH_EVENT_TIME, nexttick); - } + npth_clock_gettime (&curtime); + if (!(npth_timercmp (&curtime, &abstime, <))) + { + /* Timeout. */ + handle_tick (); + timeout.tv_sec = TIMERTICK_INTERVAL_SEC; + timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000; + npth_timeradd (&curtime, &timeout, &abstime); + } + npth_timersub (&abstime, &curtime, &timeout); /* POSIX says that fd_set should be implemented as a structure, thus a simple assignment is fine to copy the entire set. */ read_fdset = fdset; - if (time_ev) - pth_event_concat (ev, time_ev, NULL); - ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev); - if (time_ev) - pth_event_isolate (time_ev); +#ifndef HAVE_W32_SYSTEM + ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask()); + saved_errno = errno; + + while (npth_sigev_get_pending(&signo)) + handle_signal (signo); +#else + ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, NULL, NULL); + saved_errno = errno; +#endif - if (ret == -1) + if (ret == -1 && saved_errno != EINTR) { - if (pth_event_occurred (ev) - || (time_ev && pth_event_occurred (time_ev))) - { - if (pth_event_occurred (ev)) - handle_signal (signo); - if (time_ev && pth_event_occurred (time_ev)) - { - pth_event_free (time_ev, PTH_FREE_ALL); - time_ev = NULL; - handle_tick (); - } - continue; - } - log_error (_("pth_select failed: %s - waiting 1s\n"), - strerror (errno)); - pth_sleep (1); + log_error (_("npth_pselect failed: %s - waiting 1s\n"), + strerror (saved_errno)); + npth_sleep (1); continue; } - if (pth_event_occurred (ev)) - { - handle_signal (signo); - } - - if (time_ev && pth_event_occurred (time_ev)) - { - pth_event_free (time_ev, PTH_FREE_ALL); - time_ev = NULL; - handle_tick (); - } - - /* We now might create new threads and because we don't want any - signals - we are handling here - to be delivered to a new - thread. Thus we need to block those signals. */ - pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); + if (ret <= 0) + /* Timeout. Will be handled when calculating the next timeout. */ + continue; if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) { ctrl_t ctrl; plen = sizeof paddr; - fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); + fd = npth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); if (fd == -1) { log_error ("accept failed: %s\n", strerror (errno)); @@ -1318,30 +1273,27 @@ handle_connections (int listen_fd) else { char threadname[50]; + npth_t thread; snprintf (threadname, sizeof threadname-1, "conn fd=%d", fd); threadname[sizeof threadname -1] = 0; - pth_attr_set (tattr, PTH_ATTR_NAME, threadname); ctrl->thread_startup.fd = INT2FD (fd); - if (!pth_spawn (tattr, start_connection_thread, ctrl)) + ret = npth_create (&thread, &tattr, start_connection_thread, ctrl); + if (ret) { log_error ("error spawning connection handler: %s\n", - strerror (errno) ); + strerror (ret)); xfree (ctrl); close (fd); } + else + npth_setname_np (thread, threadname); } fd = -1; } - - /* Restore the signal mask. */ - pth_sigmask (SIG_SETMASK, &oldsigs, NULL); - } - pth_event_free (ev, PTH_FREE_ALL); - if (time_ev) - pth_event_free (time_ev, PTH_FREE_ALL); cleanup (); log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); + npth_attr_destroy (&tattr); } |