mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-14 21:47:19 +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:
parent
495dc68586
commit
3484457fbc
36 changed files with 1181 additions and 1190 deletions
|
@ -32,7 +32,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common
|
|||
include $(top_srcdir)/am/cmacros.am
|
||||
|
||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) \
|
||||
$(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS)
|
||||
$(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(NPTH_CFLAGS)
|
||||
|
||||
BUILT_SOURCES = no-libgcrypt.c
|
||||
|
||||
|
@ -61,7 +61,7 @@ endif
|
|||
|
||||
|
||||
dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \
|
||||
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBINTL) $(LIBICONV)
|
||||
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) $(LIBINTL) $(LIBICONV)
|
||||
if !USE_LDAPWRAPPER
|
||||
dirmngr_LDADD += $(LDAPLIBS)
|
||||
endif
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
#include "misc.h"
|
||||
|
@ -80,10 +80,10 @@ static cert_item_t cert_cache[256];
|
|||
|
||||
/* This is the global cache_lock variable. In general looking is not
|
||||
needed but it would take extra efforts to make sure that no
|
||||
indirect use of pth functions is done, so we simply lock it always.
|
||||
Note: We can't use static initialization, as that is not available
|
||||
through w32-pth. */
|
||||
static pth_rwlock_t cert_cache_lock;
|
||||
indirect use of npth functions is done, so we simply lock it
|
||||
always. Note: We can't use static initialization, as that is not
|
||||
available through w32-pth. */
|
||||
static npth_rwlock_t cert_cache_lock;
|
||||
|
||||
/* Flag to track whether the cache has been initialized. */
|
||||
static int initialization_done;
|
||||
|
@ -99,33 +99,45 @@ static unsigned int total_extra_certificates;
|
|||
static void
|
||||
init_cache_lock (void)
|
||||
{
|
||||
if (!pth_rwlock_init (&cert_cache_lock))
|
||||
int err;
|
||||
|
||||
err = npth_rwlock_init (&cert_cache_lock, NULL);
|
||||
if (err)
|
||||
log_fatal (_("can't initialize certificate cache lock: %s\n"),
|
||||
strerror (errno));
|
||||
strerror (err));
|
||||
}
|
||||
|
||||
static void
|
||||
acquire_cache_read_lock (void)
|
||||
{
|
||||
if (!pth_rwlock_acquire (&cert_cache_lock, PTH_RWLOCK_RD, FALSE, NULL))
|
||||
int err;
|
||||
|
||||
err = npth_rwlock_rdlock (&cert_cache_lock);
|
||||
if (err)
|
||||
log_fatal (_("can't acquire read lock on the certificate cache: %s\n"),
|
||||
strerror (errno));
|
||||
strerror (err));
|
||||
}
|
||||
|
||||
static void
|
||||
acquire_cache_write_lock (void)
|
||||
{
|
||||
if (!pth_rwlock_acquire (&cert_cache_lock, PTH_RWLOCK_RW, FALSE, NULL))
|
||||
int err;
|
||||
|
||||
err = npth_rwlock_wrlock (&cert_cache_lock);
|
||||
if (err)
|
||||
log_fatal (_("can't acquire write lock on the certificate cache: %s\n"),
|
||||
strerror (errno));
|
||||
strerror (err));
|
||||
}
|
||||
|
||||
static void
|
||||
release_cache_lock (void)
|
||||
{
|
||||
if (!pth_rwlock_release (&cert_cache_lock))
|
||||
int err;
|
||||
|
||||
err = npth_rwlock_unlock (&cert_cache_lock);
|
||||
if (err)
|
||||
log_fatal (_("can't release lock on the certificate cache: %s\n"),
|
||||
strerror (errno));
|
||||
strerror (err));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
|
||||
#include "crlfetch.h"
|
||||
#include "dirmngr.h"
|
||||
|
@ -72,7 +72,7 @@ register_file_reader (ksba_reader_t reader, struct reader_cb_context_s *cb_ctx)
|
|||
return;
|
||||
}
|
||||
log_info (_("reader to file mapping table full - waiting\n"));
|
||||
pth_sleep (2);
|
||||
npth_sleep (2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#ifdef HAVE_SIGNAL_H
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
|
||||
|
||||
#define JNLIB_NEED_LOG_LOGV
|
||||
|
@ -254,7 +254,7 @@ static int active_connections;
|
|||
|
||||
/* This union is used to avoid compiler warnings in case a pointer is
|
||||
64 bit and an int 32 bit. We store an integer in a pointer and get
|
||||
it back later (pth_key_getdata et al.). */
|
||||
it back later (npth_getspecific et al.). */
|
||||
union int_and_ptr_u
|
||||
{
|
||||
int aint;
|
||||
|
@ -277,27 +277,8 @@ static ldap_server_t parse_ldapserver_file (const char* filename);
|
|||
static fingerprint_list_t parse_ocsp_signer (const char *string);
|
||||
static void handle_connections (assuan_fd_t listen_fd);
|
||||
|
||||
/* Pth wrapper function definitions. */
|
||||
ASSUAN_SYSTEM_PTH_IMPL;
|
||||
|
||||
#if 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
|
||||
/* NPth wrapper function definitions. */
|
||||
ASSUAN_SYSTEM_NPTH_IMPL;
|
||||
|
||||
static const char *
|
||||
my_strusage( int level )
|
||||
|
@ -557,7 +538,7 @@ pid_suffix_callback (unsigned long *r_suffix)
|
|||
{
|
||||
union int_and_ptr_u value;
|
||||
|
||||
value.aptr = pth_key_getdata (my_tlskey_current_fd);
|
||||
value.aptr = npth_getspecific (my_tlskey_current_fd);
|
||||
*r_suffix = value.aint;
|
||||
return (*r_suffix != -1); /* Use decimal representation. */
|
||||
}
|
||||
|
@ -624,17 +605,8 @@ 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;
|
||||
rc = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
|
||||
if (rc)
|
||||
{
|
||||
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
|
||||
gpg_strerror (rc));
|
||||
}
|
||||
#endif
|
||||
npth_init ();
|
||||
|
||||
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
|
||||
|
||||
/* Check that the libraries are suitable. Do it here because
|
||||
|
@ -658,7 +630,7 @@ main (int argc, char **argv)
|
|||
assuan_set_malloc_hooks (&malloc_hooks);
|
||||
assuan_set_assuan_log_prefix (log_get_prefix (NULL));
|
||||
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);
|
||||
|
||||
|
@ -671,12 +643,12 @@ main (int argc, char **argv)
|
|||
|
||||
opt.homedir = default_homedir ();
|
||||
|
||||
/* Now with Pth running we can set the logging callback. Our
|
||||
windows implementation does not yet feature the Pth TLS
|
||||
/* Now with NPth running we can set the logging callback. Our
|
||||
windows implementation does not yet feature the NPth TLS
|
||||
functions. */
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
if (pth_key_create (&my_tlskey_current_fd, NULL))
|
||||
if (pth_key_setdata (my_tlskey_current_fd, NULL))
|
||||
if (npth_key_create (&my_tlskey_current_fd, NULL) == 0)
|
||||
if (npth_setspecific (my_tlskey_current_fd, NULL) == 0)
|
||||
log_set_pid_suffix_cb (pid_suffix_callback);
|
||||
#endif /*!HAVE_W32_SYSTEM*/
|
||||
|
||||
|
@ -1036,7 +1008,7 @@ main (int argc, char **argv)
|
|||
pid = getpid ();
|
||||
es_printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid);
|
||||
#else
|
||||
pid = pth_fork ();
|
||||
pid = fork();
|
||||
if (pid == (pid_t)-1)
|
||||
{
|
||||
log_fatal (_("error forking process: %s\n"), strerror (errno));
|
||||
|
@ -1562,7 +1534,7 @@ parse_ocsp_signer (const char *string)
|
|||
|
||||
|
||||
/* Reread parts of the configuration. Note, that this function is
|
||||
obviously not thread-safe and should only be called from the PTH
|
||||
obviously not thread-safe and should only be called from the NPTH
|
||||
signal handler.
|
||||
|
||||
Fixme: Due to the way the argument parsing works, we create a
|
||||
|
@ -1624,13 +1596,13 @@ dirmngr_sighup_action (void)
|
|||
|
||||
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
/* The signal handler. */
|
||||
static void
|
||||
handle_signal (int signo)
|
||||
{
|
||||
switch (signo)
|
||||
{
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
case SIGHUP:
|
||||
dirmngr_sighup_action ();
|
||||
break;
|
||||
|
@ -1665,12 +1637,12 @@ handle_signal (int signo)
|
|||
cleanup ();
|
||||
dirmngr_exit (0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
log_info (_("signal %d received - no action defined\n"), signo);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* This is the worker for the ticker. It is called every few seconds
|
||||
and may only do fast operations. */
|
||||
|
@ -1723,12 +1695,12 @@ start_connection_thread (void *arg)
|
|||
|
||||
if (check_nonce (fd, &socket_nonce))
|
||||
{
|
||||
log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
|
||||
log_error ("handler nonce check FAILED\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
pth_key_setdata (my_tlskey_current_fd, argval.aptr);
|
||||
npth_setspecific (my_tlskey_current_fd, argval.aptr);
|
||||
#endif
|
||||
|
||||
active_connections++;
|
||||
|
@ -1743,7 +1715,7 @@ start_connection_thread (void *arg)
|
|||
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
argval.afd = ASSUAN_INVALID_FD;
|
||||
pth_key_setdata (my_tlskey_current_fd, argval.aptr);
|
||||
npth_setspecific (my_tlskey_current_fd, argval.aptr);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
@ -1754,53 +1726,32 @@ start_connection_thread (void *arg)
|
|||
static void
|
||||
handle_connections (assuan_fd_t listen_fd)
|
||||
{
|
||||
pth_attr_t tattr;
|
||||
pth_event_t ev, time_ev;
|
||||
sigset_t sigs;
|
||||
npth_attr_t tattr;
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
int signo;
|
||||
#endif
|
||||
struct sockaddr_un paddr;
|
||||
socklen_t plen = sizeof( paddr );
|
||||
gnupg_fd_t fd;
|
||||
int nfd, ret;
|
||||
fd_set fdset, read_fdset;
|
||||
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, 1024*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "dirmngr");
|
||||
npth_attr_init (&tattr);
|
||||
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);
|
||||
#else
|
||||
/* Use a dummy event. */
|
||||
sigs = 0;
|
||||
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
|
||||
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;
|
||||
|
||||
/* Setup the fdset. It has only one member. This is because we use
|
||||
pth_select instead of pth_accept to properly sync timeouts with
|
||||
|
@ -1809,12 +1760,12 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
FD_SET (FD2INT (listen_fd), &fdset);
|
||||
nfd = FD2INT (listen_fd);
|
||||
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
|
||||
/* Main loop. */
|
||||
for (;;)
|
||||
{
|
||||
/* Make sure that our signals are not blocked. */
|
||||
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
|
||||
|
||||
/* Shutdown test. */
|
||||
if (shutdown_pending)
|
||||
{
|
||||
|
@ -1826,76 +1777,48 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
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);
|
||||
}
|
||||
|
||||
/* Take a copy of the fdset. */
|
||||
read_fdset = fdset;
|
||||
|
||||
if (time_ev)
|
||||
pth_event_concat (ev, time_ev, NULL);
|
||||
npth_clock_gettime (&curtime);
|
||||
if (!(npth_timercmp (&curtime, &abstime, <)))
|
||||
{
|
||||
/* Timeout. */
|
||||
handle_tick ();
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
}
|
||||
npth_timersub (&abstime, &curtime, &timeout);
|
||||
|
||||
ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
|
||||
#ifndef HAVE_W32_SYSTEM
|
||||
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask());
|
||||
saved_errno = errno;
|
||||
|
||||
if (time_ev)
|
||||
pth_event_isolate (time_ev);
|
||||
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 (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);
|
||||
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))
|
||||
{
|
||||
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 a new thread and because we don't want
|
||||
any signals (as we are handling them here) to be delivered to
|
||||
a new thread 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))
|
||||
{
|
||||
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));
|
||||
|
@ -1904,27 +1827,27 @@ handle_connections (assuan_fd_t listen_fd)
|
|||
{
|
||||
char threadname[50];
|
||||
union int_and_ptr_u argval;
|
||||
npth_t thread;
|
||||
|
||||
argval.afd = fd;
|
||||
snprintf (threadname, sizeof threadname-1,
|
||||
"conn fd=%d", FD2INT(fd));
|
||||
threadname[sizeof threadname -1] = 0;
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, threadname);
|
||||
if (!pth_spawn (tattr, start_connection_thread, argval.aptr))
|
||||
|
||||
ret = npth_create (&thread, &tattr, start_connection_thread, argval.aptr);
|
||||
if (ret)
|
||||
{
|
||||
log_error ("error spawning connection handler: %s\n",
|
||||
strerror (errno) );
|
||||
strerror (ret) );
|
||||
assuan_sock_close (fd);
|
||||
}
|
||||
npth_setname_np (thread, threadname);
|
||||
}
|
||||
fd = GNUPG_INVALID_FD;
|
||||
}
|
||||
}
|
||||
|
||||
pth_event_free (ev, PTH_FREE_ALL);
|
||||
if (time_ev)
|
||||
pth_event_free (time_ev, PTH_FREE_ALL);
|
||||
pth_attr_destroy (tattr);
|
||||
npth_attr_destroy (&tattr);
|
||||
cleanup ();
|
||||
log_info ("%s %s stopped\n", strusage(11), strusage(13));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#ifndef USE_LDAPWRAPPER
|
||||
# include <pth.h>
|
||||
# include <npth.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
|
@ -58,13 +58,13 @@
|
|||
#include "i18n.h"
|
||||
#include "util.h"
|
||||
|
||||
/* With the ldap wrapper, there is no need for the pth_enter and leave
|
||||
/* With the ldap wrapper, there is no need for the npth_unprotect and leave
|
||||
functions; thus we redefine them to nops. If we are not using the
|
||||
ldap wrapper process we need to include the prototype for our
|
||||
module's main function. */
|
||||
#ifdef USE_LDAPWRAPPER
|
||||
static void pth_enter (void) { }
|
||||
static void pth_leave (void) { }
|
||||
static void npth_unprotect (void) { }
|
||||
static void npth_protect (void) { }
|
||||
#else
|
||||
# include "./ldap-wrapper.h"
|
||||
#endif
|
||||
|
@ -392,9 +392,9 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
|
|||
LDAPMessage *item;
|
||||
int any = 0;
|
||||
|
||||
for (pth_enter (), item = ldap_first_entry (ld, msg), pth_leave ();
|
||||
for (npth_unprotect (), item = ldap_first_entry (ld, msg), npth_protect ();
|
||||
item;
|
||||
pth_enter (), item = ldap_next_entry (ld, item), pth_leave ())
|
||||
npth_unprotect (), item = ldap_next_entry (ld, item), npth_protect ())
|
||||
{
|
||||
BerElement *berctx;
|
||||
char *attr;
|
||||
|
@ -414,11 +414,11 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
|
|||
}
|
||||
|
||||
|
||||
for (pth_enter (), attr = my_ldap_first_attribute (ld, item, &berctx),
|
||||
pth_leave ();
|
||||
for (npth_unprotect (), attr = my_ldap_first_attribute (ld, item, &berctx),
|
||||
npth_protect ();
|
||||
attr;
|
||||
pth_enter (), attr = my_ldap_next_attribute (ld, item, berctx),
|
||||
pth_leave ())
|
||||
npth_unprotect (), attr = my_ldap_next_attribute (ld, item, berctx),
|
||||
npth_protect ())
|
||||
{
|
||||
struct berval **values;
|
||||
int idx;
|
||||
|
@ -455,9 +455,9 @@ print_ldap_entries (my_opt_t myopt, LDAP *ld, LDAPMessage *msg, char *want_attr)
|
|||
}
|
||||
}
|
||||
|
||||
pth_enter ();
|
||||
npth_unprotect ();
|
||||
values = my_ldap_get_values_len (ld, item, attr);
|
||||
pth_leave ();
|
||||
npth_protect ();
|
||||
|
||||
if (!values)
|
||||
{
|
||||
|
@ -618,19 +618,19 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
|
|||
|
||||
|
||||
set_timeout (myopt);
|
||||
pth_enter ();
|
||||
npth_unprotect ();
|
||||
ld = my_ldap_init (host, port);
|
||||
pth_leave ();
|
||||
npth_protect ();
|
||||
if (!ld)
|
||||
{
|
||||
log_error (_("LDAP init to `%s:%d' failed: %s\n"),
|
||||
host, port, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
pth_enter ();
|
||||
npth_unprotect ();
|
||||
/* Fixme: Can we use MYOPT->user or is it shared with other theeads?. */
|
||||
ret = my_ldap_simple_bind_s (ld, myopt->user, myopt->pass);
|
||||
pth_leave ();
|
||||
npth_protect ();
|
||||
if (ret)
|
||||
{
|
||||
log_error (_("binding to `%s:%d' failed: %s\n"),
|
||||
|
@ -640,13 +640,13 @@ fetch_ldap (my_opt_t myopt, const char *url, const LDAPURLDesc *ludp)
|
|||
}
|
||||
|
||||
set_timeout (myopt);
|
||||
pth_enter ();
|
||||
npth_unprotect ();
|
||||
rc = my_ldap_search_st (ld, dn, ludp->lud_scope, filter,
|
||||
myopt->multi && !myopt->attr && ludp->lud_attrs?
|
||||
ludp->lud_attrs:attrs,
|
||||
0,
|
||||
&myopt->timeout, &msg);
|
||||
pth_leave ();
|
||||
npth_protect ();
|
||||
if (rc == LDAP_SIZELIMIT_EXCEEDED && myopt->multi)
|
||||
{
|
||||
if (es_fwrite ("E\0\0\0\x09truncated", 14, 1, myopt->outstream) != 1)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
|
@ -106,12 +106,93 @@ struct outstream_cookie_s
|
|||
{
|
||||
int refcount; /* Reference counter - possible values are 1 and 2. */
|
||||
|
||||
/* We don't need a mutex for the conditions, as npth provides a
|
||||
simpler condition interface that relies on the global lock. This
|
||||
can be used if we never yield between testing the condition and
|
||||
waiting on it. */
|
||||
npth_cond_t wait_data; /* Condition that data is available. */
|
||||
npth_cond_t wait_space; /* Condition that space is available. */
|
||||
|
||||
int eof_seen; /* EOF indicator. */
|
||||
size_t buffer_len; /* The valid length of the BUFFER. */
|
||||
char buffer[4000]; /* Data ring buffer. */
|
||||
size_t buffer_len; /* The amount of data in the BUFFER. */
|
||||
size_t buffer_pos; /* The next read position of the BUFFER. */
|
||||
char buffer[4000]; /* Data buffer. */
|
||||
};
|
||||
|
||||
#define BUFFER_EMPTY(c) ((c)->buffer_len == 0)
|
||||
#define BUFFER_FULL(c) ((c)->buffer_len == DIM((c)->buffer))
|
||||
#define BUFFER_DATA_AVAILABLE(c) ((c)->buffer_len)
|
||||
#define BUFFER_SPACE_AVAILABLE(c) (DIM((c)->buffer) - (c)->buffer_len)
|
||||
#define BUFFER_INC_POS(c,n) (c)->buffer_pos = ((c)->buffer_pos + (n)) % DIM((c)->buffer)
|
||||
#define BUFFER_CUR_POS(c) (&(c)->buffer[(c)->buffer_pos])
|
||||
|
||||
static int
|
||||
buffer_get_data (struct outstream_cookie_s *cookie, char *dst, int cnt)
|
||||
{
|
||||
int amount;
|
||||
int left;
|
||||
int chunk;
|
||||
|
||||
amount = cnt;
|
||||
if (BUFFER_DATA_AVAILABLE (cookie) < amount)
|
||||
amount = BUFFER_DATA_AVAILABLE (cookie);
|
||||
left = amount;
|
||||
|
||||
/* How large is the part up to the end of the buffer array? */
|
||||
chunk = DIM(cookie->buffer) - cookie->buffer_pos;
|
||||
if (chunk > left)
|
||||
chunk = left;
|
||||
|
||||
memcpy (dst, BUFFER_CUR_POS (cookie), chunk);
|
||||
BUFFER_INC_POS (cookie, chunk);
|
||||
left -= chunk;
|
||||
dst += chunk;
|
||||
|
||||
if (left)
|
||||
{
|
||||
memcpy (dst, BUFFER_CUR_POS (cookie), left);
|
||||
BUFFER_INC_POS (cookie, left);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
buffer_put_data (struct outstream_cookie_s *cookie, const char *src, int cnt)
|
||||
{
|
||||
int amount;
|
||||
int remain;
|
||||
int left;
|
||||
int chunk;
|
||||
|
||||
remain = DIM(cookie->buffer) - cookie->buffer_len;
|
||||
|
||||
amount = cnt;
|
||||
if (remain < amount)
|
||||
amount = remain;
|
||||
left = amount;
|
||||
|
||||
/* How large is the part up to the end of the buffer array? */
|
||||
chunk = DIM(cookie->buffer) - cookie->buffer_pos;
|
||||
if (chunk > left)
|
||||
chunk = left;
|
||||
|
||||
memcpy (BUFFER_CUR_POS (cookie), src, chunk);
|
||||
BUFFER_INC_POS (cookie, chunk);
|
||||
left -= chunk;
|
||||
src += chunk;
|
||||
|
||||
if (left)
|
||||
{
|
||||
memcpy (BUFFER_CUR_POS (cookie), src, left);
|
||||
BUFFER_INC_POS (cookie, left);
|
||||
}
|
||||
|
||||
cookie->buffer_len -= amount;
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
/* The writer function for the outstream. This is used to transfer
|
||||
the output of the ldap wrapper thread to the ksba reader object. */
|
||||
|
@ -120,43 +201,42 @@ outstream_cookie_writer (void *cookie_arg, const void *buffer, size_t size)
|
|||
{
|
||||
struct outstream_cookie_s *cookie = cookie_arg;
|
||||
const char *src;
|
||||
char *dst;
|
||||
ssize_t nwritten = 0;
|
||||
int res;
|
||||
ssize_t amount = 0;
|
||||
|
||||
src = buffer;
|
||||
do
|
||||
{
|
||||
int was_empty = 0;
|
||||
|
||||
/* Wait for free space. */
|
||||
while (cookie->buffer_len == DIM (cookie->buffer))
|
||||
while (BUFFER_FULL(cookie))
|
||||
{
|
||||
/* Buffer is full: Wait for space. */
|
||||
pth_yield (NULL);
|
||||
res = npth_cond_wait (&cookie->wait_space, NULL);
|
||||
if (res)
|
||||
{
|
||||
gpg_err_set_errno (res);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (BUFFER_EMPTY(cookie))
|
||||
was_empty = 1;
|
||||
|
||||
/* Copy data. */
|
||||
dst = cookie->buffer + cookie->buffer_len;
|
||||
while (size && cookie->buffer_len < DIM (cookie->buffer))
|
||||
{
|
||||
*dst++ = *src++;
|
||||
size--;
|
||||
cookie->buffer_len++;
|
||||
nwritten++;
|
||||
}
|
||||
nwritten = buffer_put_data (cookie, buffer, size);
|
||||
size -= nwritten;
|
||||
src += nwritten;
|
||||
amount += nwritten;
|
||||
|
||||
if (was_empty)
|
||||
npth_cond_signal (&cookie->wait_data);
|
||||
}
|
||||
while (size); /* Until done. */
|
||||
|
||||
if (nwritten)
|
||||
{
|
||||
/* Signal data is available - a pth_yield is sufficient because
|
||||
the test is explicit. To increase performance we could do a
|
||||
pth_yield to the other thread and only fall back to yielding
|
||||
to any thread if that returns an error (i.e. the other thread
|
||||
is not runnable). However our w32pth does not yet support
|
||||
yielding to a specific thread, thus this won't help. */
|
||||
pth_yield (NULL);
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,7 +245,11 @@ outstream_release_cookie (struct outstream_cookie_s *cookie)
|
|||
{
|
||||
cookie->refcount--;
|
||||
if (!cookie->refcount)
|
||||
xfree (cookie);
|
||||
{
|
||||
npth_cond_destroy (&cookie->wait_data);
|
||||
npth_cond_destroy (&cookie->wait_space);
|
||||
xfree (cookie);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,6 +282,7 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
|
|||
char *dst;
|
||||
const char *src;
|
||||
size_t nread = 0;
|
||||
int was_full = 0;
|
||||
|
||||
if (!buffer && !count && !r_nread)
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Rewind is not supported. */
|
||||
|
@ -205,31 +290,26 @@ outstream_reader_cb (void *cb_value, char *buffer, size_t count,
|
|||
*r_nread = 0;
|
||||
dst = buffer;
|
||||
|
||||
while (cookie->buffer_pos == cookie->buffer_len)
|
||||
while (BUFFER_EMPTY(cookie))
|
||||
{
|
||||
if (cookie->eof_seen)
|
||||
return gpg_error (GPG_ERR_EOF);
|
||||
|
||||
/* Wait for data to become available. */
|
||||
pth_yield (NULL);
|
||||
npth_cond_wait (&cookie->wait_data, NULL);
|
||||
}
|
||||
|
||||
if (BUFFER_FULL(cookie))
|
||||
was_full = 1;
|
||||
|
||||
src = cookie->buffer + cookie->buffer_pos;
|
||||
while (count && cookie->buffer_pos < cookie->buffer_len)
|
||||
nread = buffer_get_data (cookie, buffer, count);
|
||||
|
||||
if (was_full)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
count--;
|
||||
cookie->buffer_pos++;
|
||||
nread++;
|
||||
npth_cond_signal (&cookie->wait_space);
|
||||
}
|
||||
|
||||
if (cookie->buffer_pos == cookie->buffer_len)
|
||||
cookie->buffer_pos = cookie->buffer_len = 0;
|
||||
|
||||
/* Now there should be some space available. We do this even if
|
||||
COUNT was zero so to give the writer end a chance to continue. */
|
||||
pth_yield (NULL);
|
||||
|
||||
*r_nread = nread;
|
||||
return 0; /* Success. */
|
||||
}
|
||||
|
@ -351,10 +431,12 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
|
|||
{
|
||||
gpg_error_t err;
|
||||
struct ldap_wrapper_thread_parms *parms;
|
||||
pth_attr_t tattr;
|
||||
npth_attr_t tattr;
|
||||
es_cookie_io_functions_t outstream_func = { NULL };
|
||||
struct outstream_cookie_s *outstream_cookie;
|
||||
ksba_reader_t reader;
|
||||
int res;
|
||||
npth_t thread;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
|
@ -381,6 +463,22 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
|
|||
}
|
||||
outstream_cookie->refcount++;
|
||||
|
||||
res = npth_cond_init (&outstream_cookie->wait_data, NULL);
|
||||
if (res)
|
||||
{
|
||||
free_arg_list (parms->arg_list);
|
||||
xfree (parms);
|
||||
return gpg_error_from_errno (res);
|
||||
}
|
||||
res = npth_cond_init (&outstream_cookie->wait_space, NULL);
|
||||
if (res)
|
||||
{
|
||||
npth_cond_destroy (&outstream_cookie->wait_data);
|
||||
free_arg_list (parms->arg_list);
|
||||
xfree (parms);
|
||||
return gpg_error_from_errno (res);
|
||||
}
|
||||
|
||||
err = ksba_reader_new (&reader);
|
||||
if (!err)
|
||||
err = ksba_reader_set_release_notify (reader,
|
||||
|
@ -407,27 +505,37 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *r_reader, const char *argv[])
|
|||
if (!parms->outstream)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
free_arg_list (parms->arg_list);
|
||||
ksba_reader_release (reader);
|
||||
outstream_release_cookie (outstream_cookie);
|
||||
free_arg_list (parms->arg_list);
|
||||
xfree (parms);
|
||||
return err;
|
||||
}
|
||||
outstream_cookie->refcount++;
|
||||
|
||||
tattr = pth_attr_new();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "ldap-wrapper");
|
||||
|
||||
if (pth_spawn (tattr, ldap_wrapper_thread, parms))
|
||||
parms = NULL; /* Now owned by the thread. */
|
||||
else
|
||||
res = npth_attr_init(&tattr);
|
||||
if (res)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error spawning ldap wrapper thread: %s\n",
|
||||
strerror (errno) );
|
||||
err = gpg_error_from_errno (res);
|
||||
ksba_reader_release (reader);
|
||||
free_arg_list (parms->arg_list);
|
||||
es_fclose (parms->outstream);
|
||||
xfree (parms);
|
||||
return err;
|
||||
}
|
||||
pth_attr_destroy (tattr);
|
||||
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
|
||||
|
||||
res = npth_create (&thread, &tattr, ldap_wrapper_thread, parms);
|
||||
npth_attr_destroy (&tattr);
|
||||
if (res)
|
||||
{
|
||||
err = gpg_error_from_errno (res);
|
||||
log_error ("error spawning ldap wrapper thread: %s\n",
|
||||
strerror (res) );
|
||||
}
|
||||
else
|
||||
parms = NULL; /* Now owned by the thread. */
|
||||
|
||||
if (parms)
|
||||
{
|
||||
free_arg_list (parms->arg_list);
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
#include "exechelp.h"
|
||||
|
@ -82,7 +82,7 @@
|
|||
|
||||
#define INACTIVITY_TIMEOUT (opt.ldaptimeout + 60*5) /* seconds */
|
||||
|
||||
|
||||
#define TIMERTICK_INTERVAL 2
|
||||
|
||||
/* To keep track of the LDAP wrapper state we use this structure. */
|
||||
struct wrapper_context_s
|
||||
|
@ -96,7 +96,6 @@ struct wrapper_context_s
|
|||
gpg_error_t fd_error; /* Set to the gpg_error of the last read error
|
||||
if any. */
|
||||
int log_fd; /* Connected with stderr of the ldap wrapper. */
|
||||
pth_event_t log_ev;
|
||||
ctrl_t ctrl; /* Connection data. */
|
||||
int ready; /* Internally used to mark to be removed contexts. */
|
||||
ksba_reader_t reader; /* The ksba reader object or NULL. */
|
||||
|
@ -117,8 +116,8 @@ static struct wrapper_context_s *wrapper_list;
|
|||
static int shutting_down;
|
||||
|
||||
/* Close the pth file descriptor FD and set it to -1. */
|
||||
#define SAFE_PTH_CLOSE(fd) \
|
||||
do { int _fd = fd; if (_fd != -1) { pth_close (_fd); fd = -1;} } while (0)
|
||||
#define SAFE_CLOSE(fd) \
|
||||
do { int _fd = fd; if (_fd != -1) { close (_fd); fd = -1;} } while (0)
|
||||
|
||||
|
||||
|
||||
|
@ -152,10 +151,8 @@ destroy_wrapper (struct wrapper_context_s *ctx)
|
|||
gnupg_release_process (ctx->pid);
|
||||
}
|
||||
ksba_reader_release (ctx->reader);
|
||||
SAFE_PTH_CLOSE (ctx->fd);
|
||||
SAFE_PTH_CLOSE (ctx->log_fd);
|
||||
if (ctx->log_ev)
|
||||
pth_event_free (ctx->log_ev, PTH_FREE_THIS);
|
||||
SAFE_CLOSE (ctx->fd);
|
||||
SAFE_CLOSE (ctx->log_fd);
|
||||
xfree (ctx->line);
|
||||
xfree (ctx);
|
||||
}
|
||||
|
@ -228,9 +225,9 @@ read_log_data (struct wrapper_context_s *ctx)
|
|||
int n;
|
||||
char line[256];
|
||||
|
||||
/* We must use the pth_read function for pipes, always. */
|
||||
/* We must use the npth_read function for pipes, always. */
|
||||
do
|
||||
n = pth_read (ctx->log_fd, line, sizeof line - 1);
|
||||
n = npth_read (ctx->log_fd, line, sizeof line - 1);
|
||||
while (n < 0 && errno == EINTR);
|
||||
|
||||
if (n <= 0) /* EOF or error. */
|
||||
|
@ -239,9 +236,7 @@ read_log_data (struct wrapper_context_s *ctx)
|
|||
log_error (_("error reading log from ldap wrapper %d: %s\n"),
|
||||
ctx->pid, strerror (errno));
|
||||
print_log_line (ctx, NULL);
|
||||
SAFE_PTH_CLOSE (ctx->log_fd);
|
||||
pth_event_free (ctx->log_ev, PTH_FREE_THIS);
|
||||
ctx->log_ev = NULL;
|
||||
SAFE_CLOSE (ctx->log_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -261,58 +256,72 @@ ldap_wrapper_thread (void *dummy)
|
|||
int nfds;
|
||||
struct wrapper_context_s *ctx;
|
||||
struct wrapper_context_s *ctx_prev;
|
||||
time_t current_time;
|
||||
struct timespec abstime;
|
||||
struct timespec curtime;
|
||||
struct timespec timeout;
|
||||
int saved_errno;
|
||||
fd_set fdset, read_fdset;
|
||||
int ret;
|
||||
time_t exptime;
|
||||
|
||||
(void)dummy;
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
nfds = -1;
|
||||
for (ctx = wrapper_list; ctx; ctx = ctx->next)
|
||||
{
|
||||
if (ctx->log_fd != -1)
|
||||
{
|
||||
FD_SET (ctx->log_fd, &fdset);
|
||||
if (ctx->log_fd > nfds)
|
||||
nfds = ctx->log_fd;
|
||||
}
|
||||
}
|
||||
nfds++;
|
||||
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pth_event_t timeout_ev;
|
||||
int any_action = 0;
|
||||
pth_time_t nexttick;
|
||||
|
||||
/* We timeout the pth_wait every 2 seconds. To help with power
|
||||
saving we syncronize the timeouts to the next full second. */
|
||||
nexttick = pth_timeout (2, 0);
|
||||
if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */
|
||||
{
|
||||
nexttick.tv_sec++;
|
||||
nexttick.tv_usec = 0;
|
||||
}
|
||||
timeout_ev = pth_event (PTH_EVENT_TIME, nexttick);
|
||||
if (! timeout_ev)
|
||||
/* 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;
|
||||
|
||||
npth_clock_gettime (&curtime);
|
||||
if (!(npth_timercmp (&curtime, &abstime, <)))
|
||||
{
|
||||
log_error (_("pth_event failed: %s\n"), strerror (errno));
|
||||
pth_sleep (10);
|
||||
continue;
|
||||
/* Inactivity is checked below. Nothing else to do. */
|
||||
// handle_tick ();
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
}
|
||||
npth_timersub (&abstime, &curtime, &timeout);
|
||||
|
||||
/* FIXME: For Windows, we have to use a reader thread on the
|
||||
pipe that signals an event (and a npth_select_ev variant). */
|
||||
ret = npth_pselect (nfds + 1, &read_fdset, NULL, NULL, &timeout, NULL);
|
||||
saved_errno = errno;
|
||||
|
||||
if (ret == -1 && saved_errno != EINTR)
|
||||
{
|
||||
log_error (_("npth_select failed: %s - waiting 1s\n"),
|
||||
strerror (saved_errno));
|
||||
npth_sleep (1);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ctx = wrapper_list; ctx; ctx = ctx->next)
|
||||
{
|
||||
if (ctx->log_fd != -1)
|
||||
{
|
||||
pth_event_isolate (ctx->log_ev);
|
||||
pth_event_concat (timeout_ev, ctx->log_ev, NULL);
|
||||
}
|
||||
}
|
||||
if (ret <= 0)
|
||||
/* Interrupt or timeout. Will be handled when calculating the
|
||||
next timeout. */
|
||||
continue;
|
||||
|
||||
/* Note that the read FDs are actually handles. Thus, we can
|
||||
not use pth_select, but have to use pth_wait. */
|
||||
nfds = pth_wait (timeout_ev);
|
||||
if (nfds < 0)
|
||||
{
|
||||
pth_event_free (timeout_ev, PTH_FREE_THIS);
|
||||
log_error (_("pth_wait failed: %s\n"), strerror (errno));
|
||||
pth_sleep (10);
|
||||
continue;
|
||||
}
|
||||
if (pth_event_status (timeout_ev) == PTH_STATUS_OCCURRED)
|
||||
nfds--;
|
||||
pth_event_free (timeout_ev, PTH_FREE_THIS);
|
||||
|
||||
current_time = time (NULL);
|
||||
if (current_time > INACTIVITY_TIMEOUT)
|
||||
current_time -= INACTIVITY_TIMEOUT;
|
||||
/* All timestamps before exptime should be considered expired. */
|
||||
exptime = time (NULL);
|
||||
if (exptime > INACTIVITY_TIMEOUT)
|
||||
exptime -= INACTIVITY_TIMEOUT;
|
||||
|
||||
/* Note that there is no need to lock the list because we always
|
||||
add entries at the head (with a pending event status) and
|
||||
|
@ -322,8 +331,7 @@ ldap_wrapper_thread (void *dummy)
|
|||
for (ctx = wrapper_list; ctx; ctx = ctx->next)
|
||||
{
|
||||
/* Check whether there is any logging to be done. */
|
||||
if (nfds && ctx->log_fd != -1
|
||||
&& pth_event_status (ctx->log_ev) == PTH_STATUS_OCCURRED)
|
||||
if (nfds && ctx->log_fd != -1 && FD_ISSET (ctx->log_fd, &read_fdset))
|
||||
{
|
||||
if (read_log_data (ctx))
|
||||
any_action = 1;
|
||||
|
@ -368,7 +376,7 @@ ldap_wrapper_thread (void *dummy)
|
|||
|
||||
/* Check whether we should terminate the process. */
|
||||
if (ctx->pid != (pid_t)(-1)
|
||||
&& ctx->stamp != (time_t)(-1) && ctx->stamp < current_time)
|
||||
&& ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
|
||||
{
|
||||
gnupg_kill_process (ctx->pid);
|
||||
ctx->stamp = (time_t)(-1);
|
||||
|
@ -376,7 +384,7 @@ ldap_wrapper_thread (void *dummy)
|
|||
(int)ctx->pid);
|
||||
/* We need to close the log fd because the cleanup loop
|
||||
waits for it. */
|
||||
SAFE_PTH_CLOSE (ctx->log_fd);
|
||||
SAFE_CLOSE (ctx->log_fd);
|
||||
any_action = 1;
|
||||
}
|
||||
}
|
||||
|
@ -426,24 +434,26 @@ void
|
|||
ldap_wrapper_launch_thread (void)
|
||||
{
|
||||
static int done;
|
||||
pth_attr_t tattr;
|
||||
npth_attr_t tattr;
|
||||
npth_t thread;
|
||||
int err;
|
||||
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
|
||||
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, "ldap-reaper");
|
||||
npth_attr_init (&tattr);
|
||||
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
|
||||
|
||||
if (!pth_spawn (tattr, ldap_wrapper_thread, NULL))
|
||||
err = npth_create (&thread, &tattr, ldap_wrapper_thread, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("error spawning ldap wrapper reaper thread: %s\n"),
|
||||
strerror (errno) );
|
||||
strerror (err) );
|
||||
dirmngr_exit (1);
|
||||
}
|
||||
pth_attr_destroy (tattr);
|
||||
npth_setname_np (thread, "ldap-reaper");
|
||||
npth_attr_destroy (&tattr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -456,8 +466,9 @@ void
|
|||
ldap_wrapper_wait_connections ()
|
||||
{
|
||||
shutting_down = 1;
|
||||
/* FIXME: This is a busy wait. */
|
||||
while (wrapper_list)
|
||||
pth_yield (NULL);
|
||||
npth_yield ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -482,7 +493,7 @@ ldap_wrapper_release_context (ksba_reader_t reader)
|
|||
ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
|
||||
|
||||
ctx->reader = NULL;
|
||||
SAFE_PTH_CLOSE (ctx->fd);
|
||||
SAFE_CLOSE (ctx->fd);
|
||||
if (ctx->ctrl)
|
||||
{
|
||||
ctx->ctrl->refcount--;
|
||||
|
@ -515,6 +526,7 @@ ldap_wrapper_connection_cleanup (ctrl_t ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* This is the callback used by the ldap wrapper to feed the ksba
|
||||
reader with the wrappers stdout. See the description of
|
||||
ksba_reader_set_cb for details. */
|
||||
|
@ -523,6 +535,13 @@ reader_callback (void *cb_value, char *buffer, size_t count, size_t *nread)
|
|||
{
|
||||
struct wrapper_context_s *ctx = cb_value;
|
||||
size_t nleft = count;
|
||||
int nfds;
|
||||
struct timespec abstime;
|
||||
struct timespec curtime;
|
||||
struct timespec timeout;
|
||||
int saved_errno;
|
||||
fd_set fdset, read_fdset;
|
||||
int ret;
|
||||
|
||||
/* FIXME: We might want to add some internal buffering because the
|
||||
ksba code does not do any buffering for itself (because a ksba
|
||||
|
@ -542,57 +561,73 @@ reader_callback (void *cb_value, char *buffer, size_t count, size_t *nread)
|
|||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
FD_SET (ctx->fd, &fdset);
|
||||
nfds = ctx->fd + 1;
|
||||
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
int n;
|
||||
pth_event_t evt;
|
||||
gpg_error_t err;
|
||||
|
||||
evt = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0));
|
||||
n = pth_read_ev (ctx->fd, buffer, nleft, evt);
|
||||
if (n < 0 && evt && pth_event_occurred (evt))
|
||||
{
|
||||
n = 0;
|
||||
err = dirmngr_tick (ctx->ctrl);
|
||||
npth_clock_gettime (&curtime);
|
||||
if (!(npth_timercmp (&curtime, &abstime, <)))
|
||||
{
|
||||
err = dirmngr_tick (ctx->ctrl);
|
||||
if (err)
|
||||
{
|
||||
ctx->fd_error = err;
|
||||
SAFE_PTH_CLOSE (ctx->fd);
|
||||
if (evt)
|
||||
pth_event_free (evt, PTH_FREE_THIS);
|
||||
SAFE_CLOSE (ctx->fd);
|
||||
return -1;
|
||||
}
|
||||
npth_clock_gettime (&abstime);
|
||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
||||
}
|
||||
npth_timersub (&abstime, &curtime, &timeout);
|
||||
|
||||
read_fdset = fdset;
|
||||
ret = npth_pselect (nfds, &read_fdset, NULL, NULL, &timeout, NULL);
|
||||
saved_errno = errno;
|
||||
|
||||
if (ret == -1 && saved_errno != EINTR)
|
||||
{
|
||||
ctx->fd_error = gpg_error_from_errno (errno);
|
||||
SAFE_CLOSE (ctx->fd);
|
||||
return -1;
|
||||
}
|
||||
else if (n < 0)
|
||||
if (ret <= 0)
|
||||
/* Timeout. Will be handled when calculating the next timeout. */
|
||||
continue;
|
||||
|
||||
/* This should not block now that select returned with a file
|
||||
descriptor. So it shouldn't be necessary to use npth_read
|
||||
(and it is slightly dangerous in the sense that a concurrent
|
||||
thread might (accidentially?) change the status of ctx->fd
|
||||
before we read. FIXME: Set ctx->fd to nonblocking? */
|
||||
n = read (ctx->fd, buffer, nleft);
|
||||
if (n < 0)
|
||||
{
|
||||
ctx->fd_error = gpg_error_from_errno (errno);
|
||||
SAFE_PTH_CLOSE (ctx->fd);
|
||||
if (evt)
|
||||
pth_event_free (evt, PTH_FREE_THIS);
|
||||
SAFE_CLOSE (ctx->fd);
|
||||
return -1;
|
||||
}
|
||||
else if (!n)
|
||||
{
|
||||
if (nleft == count)
|
||||
{
|
||||
if (evt)
|
||||
pth_event_free (evt, PTH_FREE_THIS);
|
||||
return -1; /* EOF. */
|
||||
}
|
||||
return -1; /* EOF. */
|
||||
break;
|
||||
}
|
||||
nleft -= n;
|
||||
buffer += n;
|
||||
if (evt)
|
||||
pth_event_free (evt, PTH_FREE_THIS);
|
||||
if (n > 0 && ctx->stamp != (time_t)(-1))
|
||||
ctx->stamp = time (NULL);
|
||||
}
|
||||
*nread = count - nleft;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Fork and exec the LDAP wrapper and returns a new libksba reader
|
||||
|
@ -702,12 +737,6 @@ ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
|
|||
ctx->printable_pid = (int) pid;
|
||||
ctx->fd = outpipe[0];
|
||||
ctx->log_fd = errpipe[0];
|
||||
ctx->log_ev = pth_event (PTH_EVENT_FD | PTH_UNTIL_FD_READABLE, ctx->log_fd);
|
||||
if (! ctx->log_ev)
|
||||
{
|
||||
xfree (ctx);
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
ctx->ctrl = ctrl;
|
||||
ctrl->refcount++;
|
||||
ctx->stamp = time (NULL);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pth.h>
|
||||
#include <npth.h>
|
||||
|
||||
#include "dirmngr.h"
|
||||
#include "exechelp.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue