1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Port to npth.

* configure.ac: Don't check for PTH but for NPTH.
(AH_BOTTOM): Remove PTH_SYSCALL_SOFT.
(have_pth): Rename to ...
(have_npth): ... this.
(USE_GNU_NPTH): Rename to ...
(USE_GNU_PTH): ... this.
* m4/npth.m4: New file.
* agent/Makefile.am, agent/cache.c, agent/call-pinentry.c,
agent/call-scd.c, agent/findkey.c, agent/gpg-agent.c,
agent/trustlist.c, common/Makefile.am, common/estream.c,
common/exechelp-posix.c, common/exechelp-w32.c,
common/exechelp-w32ce.c, common/http.c, common/init.c,
common/sysutils.c, dirmngr/Makefile.am, dirmngr/crlfetch.c,
dirmngr/dirmngr.c, dirmngr/dirmngr_ldap.c, dirmngr/ldap-wrapper-ce.c,
dirmngr/ldap-wrapper.c, dirmngr/ldap.c, g13/Makefile.am,
g13/call-gpg.c, g13/g13.c, g13/runner.c, scd/Makefile.am,
scd/apdu.c, scd/app.c, scd/ccid-driver.c, scd/command.c,
scd/scdaemon.c, tools/Makefile.am: Port to npth.
This commit is contained in:
Marcus Brinkmann 2012-01-03 22:12:37 +01:00 committed by Werner Koch
parent 495dc68586
commit 7a7a597827
36 changed files with 969 additions and 1098 deletions

View file

@ -38,7 +38,7 @@
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
#include <pth.h>
#include <npth.h>
#define JNLIB_NEED_LOG_LOGV
#define JNLIB_NEED_AFLOCAL
@ -268,6 +268,9 @@ static char *current_logfile;
watched. */
static pid_t parent_pid = (pid_t)(-1);
/* Number of active connections. */
static int active_connections;
/*
Local prototypes.
@ -287,29 +290,7 @@ static void check_own_socket (void);
static int check_for_running_agent (int silent, int mode);
/* Pth wrapper function definitions. */
ASSUAN_SYSTEM_PTH_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
#ifndef PTH_HAVE_PTH_THREAD_ID
static unsigned long pth_thread_id (void)
{
return (unsigned long)pth_self ();
}
#endif
ASSUAN_SYSTEM_NPTH_IMPL;
/*
@ -624,19 +605,7 @@ main (int argc, char **argv )
i18n_init ();
init_common_subsystems (&argc, &argv);
#ifdef USE_GCRY_THREAD_CBS
/* Libgcrypt requires us to register the threading model first.
Note that this will also do the pth_init. */
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. */
@ -651,7 +620,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);
@ -1091,19 +1060,9 @@ main (int argc, char **argv )
/* Close the socket FD. */
close (fd);
/* Note that we used a standard fork so that Pth runs in
both the parent and the child. The pth_fork would
terminate Pth in the child but that is not the way we
want it. Thus we use a plain fork and terminate Pth here
in the parent. The pth_kill may or may not work reliable
but it should not harm to call it. Because Pth fiddles
with the signal mask the signal mask might not be correct
right now and thus we restore it. That is not strictly
necessary but some programs falsely assume a cleared
signal mask. */
#warning need to do something about pth_kill - see bug#1320
if ( !pth_kill () )
log_error ("pth_kill failed in forked process\n");
/* The signal mask might not be correct right now and thus
we restore it. That is not strictly necessary but some
programs falsely assume a cleared signal mask. */
#ifdef HAVE_SIGPROCMASK
if (startup_signal_mask_valid)
@ -1787,8 +1746,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 open connections\n",
active_connections);
shutdown_pending++;
if (shutdown_pending > 2)
{
@ -1838,19 +1797,20 @@ start_connection_thread (void *arg)
if (check_nonce (ctrl, &socket_nonce))
{
log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
log_error ("handler 0x%lx nonce check FAILED\n",
(unsigned long) npth_self());
return NULL;
}
agent_init_default_ctrl (ctrl);
if (opt.verbose)
log_info (_("handler 0x%lx for fd %d started\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd);
if (opt.verbose)
log_info (_("handler 0x%lx for fd %d terminated\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
@ -1870,12 +1830,12 @@ start_connection_thread_ssh (void *arg)
agent_init_default_ctrl (ctrl);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d started\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
start_command_handler_ssh (ctrl, ctrl->thread_startup.fd);
if (opt.verbose)
log_info (_("ssh handler 0x%lx for fd %d terminated\n"),
pth_thread_id (), FD2INT(ctrl->thread_startup.fd));
(unsigned long) npth_self(), FD2INT(ctrl->thread_startup.fd));
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
@ -1888,9 +1848,7 @@ start_connection_thread_ssh (void *arg)
static void
handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
{
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;
@ -1898,37 +1856,23 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
int ret;
gnupg_fd_t fd;
int nfd;
int saved_errno;
struct timespec abstime;
struct timespec curtime;
struct timespec timeout;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
ret = npth_attr_init(&tattr);
/* FIXME: Check error. */
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
#ifndef HAVE_W32_SYSTEM /* fixme */
/* Make sure that the signals we are going to handle are not blocked
and create an event object for them. We also set the default
action to ignore because we use an Pth event to get notified
about signals. This avoids that the default action is taken in
case soemthing goes wrong within Pth. The problem might also be
a Pth bug. */
sigemptyset (&sigs );
{
static const int mysigs[] = { SIGHUP, SIGUSR1, SIGUSR2, SIGINT, SIGTERM };
struct sigaction sa;
int i;
for (i=0; i < DIM (mysigs); i++)
{
sigemptyset (&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigaction (mysigs[i], &sa, NULL);
sigaddset (&sigs, mysigs[i]);
}
}
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
#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 ();
#else
# ifdef HAVE_W32CE_SYSTEM
/* Use a dummy event. */
@ -1940,7 +1884,6 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
signo = 0;
# endif
#endif
time_ev = NULL;
/* Set a flag to tell call-scd.c that it may enable event
notifications. */
@ -1956,15 +1899,15 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
nfd = FD2INT (listen_fd_ssh);
}
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL;
for (;;)
{
/* Make sure that our signals are not blocked. */
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
/* Shutdown test. */
if (shutdown_pending)
{
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
if (active_connections == 0)
break; /* ready */
/* Do not accept new connections but keep on running the
@ -1972,88 +1915,52 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
FD_ZERO (&fdset);
}
/* Create a timeout event if needed. To help with power saving
we syncronize the ticks to the next full second. */
if (!time_ev)
{
pth_time_t nexttick;
nexttick = pth_timeout (TIMERTICK_INTERVAL, 0);
if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */
{
nexttick.tv_sec++;
nexttick.tv_usec = 0;
}
time_ev = pth_event (PTH_EVENT_TIME, nexttick);
}
/* 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);
if (ret == -1)
npth_clock_gettime (&curtime);
if (!(npth_timercmp (&curtime, &abstime, <)))
{
if (pth_event_occurred (ev)
|| (time_ev && pth_event_occurred (time_ev)))
{
if (pth_event_occurred (ev))
{
#if defined(HAVE_W32_SYSTEM) && defined(PTH_EVENT_HANDLE)
agent_sigusr2_action ();
#else
handle_signal (signo);
/* Timeout. */
handle_tick ();
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL;
}
npth_timersub (&abstime, &curtime, &timeout);
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask());
saved_errno = errno;
#ifndef HAVE_W32_SYSTEM
while (npth_sigev_get_pending(&signo))
handle_signal (signo);
#endif
}
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);
#if defined(HAVE_W32_SYSTEM) && defined(PTH_EVENT_HANDLE)
if (pth_event_occurred (ev))
agent_sigusr2_action ();
#endif
if (ret == -1 && saved_errno != EINTR)
{
log_error (_("npth_pselect failed: %s - waiting 1s\n"),
strerror (saved_errno));
npth_sleep (1);
continue;
}
if (pth_event_occurred (ev))
{
#if defined(HAVE_W32_SYSTEM) && defined(PTH_EVENT_HANDLE)
agent_sigusr2_action ();
#else
handle_signal (signo);
#endif
}
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 (as we are handling them here) to be delivered to a
new thread. Thus we need to block those signals. */
pth_sigmask (SIG_BLOCK, &sigs, NULL);
if (ret <= 0)
/* Interrupt or timeout. Will be handled when calculating the
next timeout. */
continue;
if (!shutdown_pending && FD_ISSET (FD2INT (listen_fd), &read_fdset))
{
ctrl_t ctrl;
plen = sizeof paddr;
fd = INT2FD (pth_accept (FD2INT(listen_fd),
(struct sockaddr *)&paddr, &plen));
fd = INT2FD (npth_accept (FD2INT(listen_fd),
(struct sockaddr *)&paddr, &plen));
if (fd == GNUPG_INVALID_FD)
{
log_error ("accept failed: %s\n", strerror (errno));
@ -2073,20 +1980,18 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
}
else
{
char threadname[50];
npth_t thread;
snprintf (threadname, sizeof threadname-1,
"conn fd=%d (gpg)", FD2INT(fd));
threadname[sizeof threadname -1] = 0;
pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
ctrl->thread_startup.fd = 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));
assuan_sock_close (fd);
xfree (ctrl);
}
}
fd = GNUPG_INVALID_FD;
}
@ -2097,8 +2002,8 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
ctrl_t ctrl;
plen = sizeof paddr;
fd = INT2FD(pth_accept (FD2INT(listen_fd_ssh),
(struct sockaddr *)&paddr, &plen));
fd = INT2FD(npth_accept (FD2INT(listen_fd_ssh),
(struct sockaddr *)&paddr, &plen));
if (fd == GNUPG_INVALID_FD)
{
log_error ("accept failed for ssh: %s\n", strerror (errno));
@ -2118,18 +2023,15 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
}
else
{
char threadname[50];
pthread_t thread;
agent_init_default_ctrl (ctrl);
snprintf (threadname, sizeof threadname-1,
"conn fd=%d (ssh)", FD2INT(fd));
threadname[sizeof threadname -1] = 0;
pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
ctrl->thread_startup.fd = fd;
if (!pth_spawn (tattr, start_connection_thread_ssh, ctrl) )
ret = npth_create (&thread, &tattr, start_connection_thread_ssh, ctrl);
if (ret)
{
log_error ("error spawning ssh connection handler: %s\n",
strerror (errno) );
strerror (ret));
assuan_sock_close (fd);
xfree (ctrl);
}
@ -2138,11 +2040,9 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
}
}
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);
}
@ -2234,7 +2134,9 @@ static void
check_own_socket (void)
{
char *sockname;
pth_attr_t tattr;
npth_t thread;
npth_attr_t tattr;
int err;
if (!opt.use_standard_socket)
return; /* This check makes only sense in standard socket mode. */
@ -2246,15 +2148,14 @@ check_own_socket (void)
if (!sockname)
return; /* Out of memory. */
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "check-own-socket");
if (!pth_spawn (tattr, check_own_socket_thread, sockname))
log_error ("error spawning check_own_socket_thread: %s\n",
strerror (errno) );
pth_attr_destroy (tattr);
err = npth_attr_init (&tattr);
if (err)
return;
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
err = npth_create (&thread, &tattr, check_own_socket_thread, sockname);
if (err)
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
npth_attr_destroy (&tattr);
}