1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-21 10:09:57 +01: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
parent 495dc68586
commit 3484457fbc
36 changed files with 1181 additions and 1190 deletions

View File

@ -72,9 +72,9 @@ gpg_agent_res_deps =
#endif
gpg_agent_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
gpg_agent_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
gpg_agent_LDADD = $(commonpth_libs) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV)
gpg_agent_LDFLAGS = $(extra_bin_ldflags) $(gpg_agent_res_ldflags)
gpg_agent_DEPENDENCIES = $(gpg_agent_res_deps)

View File

@ -24,7 +24,7 @@
#include <string.h>
#include <time.h>
#include <assert.h>
#include <pth.h>
#include <npth.h>
#include "agent.h"
@ -33,7 +33,7 @@
/* A mutex used to protect the encryption. This is required because
we use one context to do all encryption and decryption. */
static pth_mutex_t encryption_lock;
static npth_mutex_t encryption_lock;
/* The encryption context. This is the only place where the
encryption key for all cached entries is available. It would be nice
to keep this (or just the key) in some hardware device, for example
@ -71,11 +71,12 @@ static ITEM thecache;
void
initialize_module_cache (void)
{
if (!pth_mutex_init (&encryption_lock))
{
gpg_error_t err = gpg_error_from_syserror ();
log_fatal ("error initializing cache module: %s\n", gpg_strerror (err));
}
int err;
err = npth_mutex_init (&encryption_lock, NULL);
if (err)
log_fatal ("error initializing cache module: %s\n", strerror (err));
}
@ -98,12 +99,14 @@ init_encryption (void)
{
gpg_error_t err;
void *key;
int res;
if (encryption_handle)
return 0; /* Shortcut - Already initialized. */
if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
log_fatal ("failed to acquire cache encryption mutex\n");
res = npth_mutex_lock (&encryption_lock);
if (res)
log_fatal ("failed to acquire cache encryption mutex: %s\n", strerror (res));
err = gcry_cipher_open (&encryption_handle, GCRY_CIPHER_AES128,
GCRY_CIPHER_MODE_AESWRAP, GCRY_CIPHER_SECURE);
@ -127,8 +130,9 @@ init_encryption (void)
log_error ("error initializing cache encryption context: %s\n",
gpg_strerror (err));
if (!pth_mutex_release (&encryption_lock))
log_fatal ("failed to release cache encryption mutex\n");
res = npth_mutex_unlock (&encryption_lock);
if (res)
log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
return err? gpg_error (GPG_ERR_NOT_INITIALIZED) : 0;
}
@ -148,6 +152,7 @@ new_data (const char *string, struct secret_data_s **r_data)
struct secret_data_s *d, *d_enc;
size_t length;
int total;
int res;
*r_data = NULL;
@ -178,13 +183,17 @@ new_data (const char *string, struct secret_data_s **r_data)
}
d_enc->totallen = total;
if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
log_fatal ("failed to acquire cache encryption mutex\n");
res = npth_mutex_lock (&encryption_lock);
if (res)
log_fatal ("failed to acquire cache encryption mutex: %s\n",
strerror (res));
err = gcry_cipher_encrypt (encryption_handle, d_enc->data, total,
d->data, total - 8);
xfree (d);
if (!pth_mutex_release (&encryption_lock))
log_fatal ("failed to release cache encryption mutex\n");
res = npth_mutex_unlock (&encryption_lock);
if (res)
log_fatal ("failed to release cache encryption mutex: %s\n", strerror (res));
if (err)
{
xfree (d_enc);
@ -378,6 +387,7 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
gpg_error_t err;
ITEM r;
char *value = NULL;
int res;
if (cache_mode == CACHE_MODE_IGNORE)
return NULL;
@ -405,13 +415,17 @@ agent_get_cache (const char *key, cache_mode_t cache_mode)
err = gpg_error_from_syserror ();
else
{
if (!pth_mutex_acquire (&encryption_lock, 0, NULL))
log_fatal ("failed to acquire cache encryption mutex\n");
res = npth_mutex_lock (&encryption_lock);
if (res)
log_fatal ("failed to acquire cache encryption mutex: %s\n",
strerror (res));
err = gcry_cipher_decrypt (encryption_handle,
value, r->pw->totallen - 8,
r->pw->data, r->pw->totallen);
if (!pth_mutex_release (&encryption_lock))
log_fatal ("failed to release cache encryption mutex\n");
res = npth_mutex_unlock (&encryption_lock);
if (res)
log_fatal ("failed to release cache encryption mutex: %s\n",
strerror (res));
}
if (err)
{

View File

@ -32,7 +32,7 @@
# include <sys/types.h>
# include <signal.h>
#endif
#include <pth.h>
#include <npth.h>
#include "agent.h"
#include <assuan.h>
@ -62,10 +62,10 @@ static assuan_context_t entry_ctx;
static ctrl_t entry_owner;
/* A mutex used to serialize access to the pinentry. */
static pth_mutex_t entry_lock;
static npth_mutex_t entry_lock;
/* The thread ID of the popup working thread. */
static pth_t popup_tid;
static npth_t popup_tid;
/* A flag used in communication between the popup working thread and
its stop function. */
@ -95,39 +95,19 @@ initialize_module_call_pinentry (void)
if (!initialized)
{
if (pth_mutex_init (&entry_lock))
if (npth_mutex_init (&entry_lock, NULL))
initialized = 1;
}
}
static void
dump_mutex_state (pth_mutex_t *m)
{
#ifdef _W32_PTH_H
(void)m;
log_printf ("unknown under W32");
#else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
log_printf ("not_initialized");
else if (!(m->mx_state & PTH_MUTEX_LOCKED))
log_printf ("not_locked");
else
log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
#endif
}
/* This function may be called to print infromation pertaining to the
current state of this module to the log. */
void
agent_query_dump_state (void)
{
log_info ("agent_query_dump_state: entry_lock=");
dump_mutex_state (&entry_lock);
log_printf ("\n");
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%lx\n",
entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
}
@ -151,13 +131,15 @@ static int
unlock_pinentry (int rc)
{
assuan_context_t ctx = entry_ctx;
int err;
entry_ctx = NULL;
if (!pth_mutex_release (&entry_lock))
err = npth_mutex_unlock (&entry_lock);
if (err)
{
log_error ("failed to release the entry lock\n");
log_error ("failed to release the entry lock: %s\n", strerror (err));
if (!rc)
rc = gpg_error (GPG_ERR_INTERNAL);
rc = gpg_error_from_errno (err);
}
assuan_release (ctx);
return rc;
@ -222,30 +204,31 @@ getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
static int
start_pinentry (ctrl_t ctrl)
{
int rc;
int rc = 0;
const char *pgmname;
assuan_context_t ctx;
const char *argv[5];
int no_close_list[3];
int i;
pth_event_t evt;
const char *tmpstr;
unsigned long pinentry_pid;
const char *value;
struct timespec abstime;
int err;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
npth_clock_gettime (&abstime);
abstime.tv_sec += LOCK_TIMEOUT;
err = npth_mutex_timedlock (&entry_lock, &abstime);
if (err)
{
if (pth_event_occurred (evt))
rc = gpg_error (GPG_ERR_TIMEOUT);
if (err == ETIMEDOUT)
rc = gpg_error (GPG_ERR_TIMEOUT);
else
rc = gpg_error (GPG_ERR_INTERNAL);
pth_event_free (evt, PTH_FREE_THIS);
rc = gpg_error_from_errno (rc);
log_error (_("failed to acquire the pinentry lock: %s\n"),
gpg_strerror (rc));
return rc;
}
pth_event_free (evt, PTH_FREE_THIS);
entry_owner = ctrl;
@ -484,33 +467,37 @@ start_pinentry (ctrl_t ctrl)
int
pinentry_active_p (ctrl_t ctrl, int waitseconds)
{
int err;
(void)ctrl;
if (waitseconds > 0)
{
pth_event_t evt;
struct timespec abstime;
int rc;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
npth_clock_gettime (&abstime);
abstime.tv_sec += waitseconds;
err = npth_mutex_timedlock (&entry_lock, &abstime);
if (err)
{
if (pth_event_occurred (evt))
if (err == ETIMEDOUT)
rc = gpg_error (GPG_ERR_TIMEOUT);
else
rc = gpg_error (GPG_ERR_INTERNAL);
pth_event_free (evt, PTH_FREE_THIS);
return rc;
}
pth_event_free (evt, PTH_FREE_THIS);
}
else
{
if (!pth_mutex_acquire (&entry_lock, 1, NULL))
err = npth_mutex_trylock (&entry_lock);
if (err)
return gpg_error (GPG_ERR_LOCKED);
}
if (!pth_mutex_release (&entry_lock))
log_error ("failed to release the entry lock at %d\n", __LINE__);
err = npth_mutex_unlock (&entry_lock);
if (err)
log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
strerror (errno));
return 0;
}
@ -1185,7 +1172,8 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
{
int rc;
char line[ASSUAN_LINELENGTH];
pth_attr_t tattr;
npth_attr_t tattr;
int err;
if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
return gpg_error (GPG_ERR_CANCELED);
@ -1212,22 +1200,22 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
return unlock_pinentry (rc);
}
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
err = npth_attr_init (&tattr);
if (err)
return unlock_pinentry (gpg_error_from_errno (err));
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
popup_finished = 0;
popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
if (!popup_tid)
err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
npth_attr_destroy (&tattr);
if (err)
{
rc = gpg_error_from_syserror ();
rc = gpg_error_from_errno (err);
log_error ("error spawning popup message handler: %s\n",
strerror (errno) );
pth_attr_destroy (tattr);
strerror (err) );
return unlock_pinentry (rc);
}
pth_attr_destroy (tattr);
npth_setname_np (popup_tid, "popup-message");
return 0;
}
@ -1277,11 +1265,13 @@ agent_popup_message_stop (ctrl_t ctrl)
#endif
/* Now wait for the thread to terminate. */
rc = pth_join (popup_tid, NULL);
rc = npth_join (popup_tid, NULL);
if (!rc)
log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
strerror (errno));
popup_tid = NULL;
/* Thread IDs are opaque, but we try our best here by resetting it
to the same content that a static global variable has. */
memset (&popup_tid, '\0', sizeof (popup_tid));
entry_owner = NULL;
/* Now we can close the connection. */

View File

@ -34,7 +34,7 @@
#ifndef HAVE_W32_SYSTEM
#include <sys/wait.h>
#endif
#include <pth.h>
#include <npth.h>
#include "agent.h"
#include <assuan.h>
@ -93,7 +93,7 @@ struct inq_needpin_s
static struct scd_local_s *scd_local_list;
/* A Mutex used inside the start_scd function. */
static pth_mutex_t start_scd_lock;
static npth_mutex_t start_scd_lock;
/* A malloced string with the name of the socket to be used for
additional connections. May be NULL if not provided by
@ -120,47 +120,29 @@ static gpg_error_t membuf_data_cb (void *opaque,
/* This function must be called once to initialize this module. This
has to be done before a second thread is spawned. We can't do the
static initialization because Pth emulation code might not be able
static initialization because NPth emulation code might not be able
to do a static init; in particular, it is not possible for W32. */
void
initialize_module_call_scd (void)
{
static int initialized;
int err;
if (!initialized)
{
if (!pth_mutex_init (&start_scd_lock))
log_fatal ("error initializing mutex: %s\n", strerror (errno));
err = npth_mutex_init (&start_scd_lock, NULL);
if (err)
log_fatal ("error initializing mutex: %s\n", strerror (err));
initialized = 1;
}
}
static void
dump_mutex_state (pth_mutex_t *m)
{
#ifdef _W32_PTH_H
(void)m;
log_printf ("unknown under W32");
#else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
log_printf ("not_initialized");
else if (!(m->mx_state & PTH_MUTEX_LOCKED))
log_printf ("not_locked");
else
log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
#endif
}
/* This function may be called to print infromation pertaining to the
current state of this module to the log. */
void
agent_scd_dump_state (void)
{
log_info ("agent_scd_dump_state: scd_lock=");
dump_mutex_state (&start_scd_lock);
log_printf ("\n");
log_info ("agent_scd_dump_state: primary_scd_ctx=%p pid=%ld reusable=%d\n",
primary_scd_ctx,
(long)assuan_get_pid (primary_scd_ctx),
@ -253,10 +235,11 @@ start_scd (ctrl_t ctrl)
/* We need to protect the following code. */
if (!pth_mutex_acquire (&start_scd_lock, 0, NULL))
rc = npth_mutex_lock (&start_scd_lock);
if (rc)
{
log_error ("failed to acquire the start_scd lock: %s\n",
strerror (errno));
strerror (rc));
return gpg_error (GPG_ERR_INTERNAL);
}
@ -420,8 +403,9 @@ start_scd (ctrl_t ctrl)
{
ctrl->scd_local->ctx = ctx;
}
if (!pth_mutex_release (&start_scd_lock))
log_error ("failed to release the start_scd lock: %s\n", strerror (errno));
rc = npth_mutex_unlock (&start_scd_lock);
if (rc)
log_error ("failed to release the start_scd lock: %s\n", strerror (rc));
return err;
}
@ -440,35 +424,36 @@ agent_scd_check_running (void)
void
agent_scd_check_aliveness (void)
{
pth_event_t evt;
pid_t pid;
#ifdef HAVE_W32_SYSTEM
DWORD rc;
#else
int rc;
#endif
struct timespec abstime;
int err;
if (!primary_scd_ctx)
return; /* No scdaemon running. */
/* This is not a critical function so we use a short timeout while
acquiring the lock. */
evt = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0));
if (!pth_mutex_acquire (&start_scd_lock, 0, evt))
npth_clock_gettime (&abstime);
abstime.tv_sec += 1;
err = npth_mutex_timedlock (&start_scd_lock, &abstime);
if (err)
{
if (pth_event_occurred (evt))
if (err == ETIMEDOUT)
{
if (opt.verbose > 1)
log_info ("failed to acquire the start_scd lock while"
" doing an aliveness check: %s\n", "timeout");
" doing an aliveness check: %s\n", strerror (err));
}
else
log_error ("failed to acquire the start_scd lock while"
" doing an aliveness check: %s\n", strerror (errno));
pth_event_free (evt, PTH_FREE_THIS);
" doing an aliveness check: %s\n", strerror (err));
return;
}
pth_event_free (evt, PTH_FREE_THIS);
if (primary_scd_ctx)
{
@ -513,9 +498,10 @@ agent_scd_check_aliveness (void)
}
}
if (!pth_mutex_release (&start_scd_lock))
err = npth_mutex_unlock (&start_scd_lock);
if (err)
log_error ("failed to release the start_scd lock while"
" doing the aliveness check: %s\n", strerror (errno));
" doing the aliveness check: %s\n", strerror (err));
}

View File

@ -29,7 +29,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
#include <pth.h> /* (we use pth_sleep) */
#include <npth.h> /* (we use pth_sleep) */
#include "agent.h"
#include "i18n.h"
@ -382,7 +382,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
{
/* We need to give the other thread a chance to actually put
it into the cache. */
pth_sleep (1);
npth_sleep (1);
goto retry;
}
/* Timeout - better call pinentry now the plain way. */

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)
@ -1432,9 +1391,9 @@ get_agent_ssh_socket_name (void)
void *
get_agent_scd_notify_event (void)
{
static HANDLE the_event;
static HANDLE the_event = INVALID_HANDLE_VALUE;
if (!the_event)
if (the_event == INVALID_HANDLE_VALUE)
{
HANDLE h, h2;
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
@ -1758,6 +1717,7 @@ agent_sigusr2_action (void)
}
#ifndef HAVE_W32_SYSTEM
/* The signal handler for this program. It is expected to be run in
its own trhead and not in the context of a signal handler. */
static void
@ -1765,7 +1725,6 @@ handle_signal (int signo)
{
switch (signo)
{
#ifndef HAVE_W32_SYSTEM
case SIGHUP:
agent_sighup_action ();
break;
@ -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)
{
@ -1805,12 +1764,12 @@ handle_signal (int signo)
cleanup ();
agent_exit (0);
break;
#endif
default:
log_info ("signal %d received - no action defined\n", signo);
}
}
#endif
/* Check the nonce on a new connection. This is a NOP unless we we
are using our Unix domain socket emulation under Windows. */
@ -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,59 +1848,46 @@ 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;
int signo;
npth_attr_t tattr;
struct sockaddr_un paddr;
socklen_t plen;
fd_set fdset, read_fdset;
int ret;
gnupg_fd_t fd;
int nfd;
int saved_errno;
struct timespec abstime;
struct timespec curtime;
struct timespec timeout;
#ifdef HAVE_W32_SYSTEM
HANDLE events[2];
int events_set;
#else
int signo;
#endif
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);
if (ret)
log_fatal ("error allocating thread attributes: %s\n",
gpg_strerror (ret));
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. */
sigs = 0;
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
# else
sigs = 0;
ev = pth_event (PTH_EVENT_HANDLE, get_agent_scd_notify_event ());
signo = 0;
events[0] = get_agent_scd_notify_event ();
events[1] = INVALID_HANDLE_VALUE;
# endif
#endif
time_ev = NULL;
/* Set a flag to tell call-scd.c that it may enable event
notifications. */
@ -1956,15 +1903,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 +1919,55 @@ 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 ();
/* Timeout. */
handle_tick ();
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL;
}
npth_timersub (&abstime, &curtime, &timeout);
#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
handle_signal (signo);
events_set = 0;
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, events, &events_set);
saved_errno = errno;
/* This is valid even if npth_eselect returns an error. */
if (events_set & 1)
agent_sigusr2_action ();
#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 (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 +1987,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 +2009,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 +2030,15 @@ handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh)
}
else
{
char threadname[50];
npth_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 +2047,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 +2141,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 +2155,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);
}

View File

@ -26,7 +26,7 @@
#include <assert.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pth.h>
#include <npth.h>
#include "agent.h"
#include <assuan.h> /* fixme: need a way to avoid assuan calls here */
@ -53,7 +53,7 @@ typedef struct trustitem_s trustitem_t;
static trustitem_t *trusttable;
static size_t trusttablesize;
/* A mutex used to protect the table. */
static pth_mutex_t trusttable_lock;
static npth_mutex_t trusttable_lock;
@ -81,11 +81,13 @@ void
initialize_module_trustlist (void)
{
static int initialized;
int err;
if (!initialized)
{
if (!pth_mutex_init (&trusttable_lock))
log_fatal ("error initializing mutex: %s\n", strerror (errno));
err = npth_mutex_init (&trusttable_lock, NULL);
if (err)
log_fatal ("error initializing mutex: %s\n", strerror (err));
initialized = 1;
}
}
@ -96,15 +98,21 @@ initialize_module_trustlist (void)
static void
lock_trusttable (void)
{
if (!pth_mutex_acquire (&trusttable_lock, 0, NULL))
log_fatal ("failed to acquire mutex in %s\n", __FILE__);
int err;
err = npth_mutex_lock (&trusttable_lock);
if (err)
log_fatal ("failed to acquire mutex in %s: %s\n", __FILE__, strerror (err));
}
static void
unlock_trusttable (void)
{
if (!pth_mutex_release (&trusttable_lock))
log_fatal ("failed to release mutex in %s\n", __FILE__);
int err;
err = npth_mutex_unlock (&trusttable_lock);
if (err)
log_fatal ("failed to release mutex in %s: %s\n", __FILE__, strerror (err));
}

View File

@ -106,22 +106,22 @@ else
common_sources += exechelp-posix.c
endif
# Sources only useful without PTH.
without_pth_sources = \
# Sources only useful without NPTH.
without_npth_sources = \
get-passphrase.c get-passphrase.h
libcommon_a_SOURCES = $(jnlib_sources) $(common_sources) $(without_pth_sources)
libcommon_a_SOURCES = $(jnlib_sources) $(common_sources) $(without_npth_sources)
if USE_DNS_SRV
libcommon_a_SOURCES += srv.c
endif
libcommon_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) -DWITHOUT_GNU_PTH=1
libcommon_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) -DWITHOUT_NPTH=1
libcommonpth_a_SOURCES = $(jnlib_sources) $(common_sources)
if USE_DNS_SRV
libcommonpth_a_SOURCES += srv.c
endif
libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
if !HAVE_W32CE_SYSTEM
libsimple_pwquery_a_SOURCES = \

View File

@ -85,13 +85,13 @@
# include <gpg-error.h> /* ERRNO replacement. */
#endif
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_PTH
# undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_NPTH
# undef USE_NPTH
#endif
#ifdef HAVE_PTH
# include <pth.h>
#ifdef HAVE_NPTH
# include <npth.h>
#endif
/* This is for the special hack to use estream.c in GnuPG. */
@ -159,7 +159,7 @@ typedef void (*func_free_t) (void *mem);
/* Locking. */
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
typedef pth_mutex_t estream_mutex_t;
# define ESTREAM_MUTEX_INITIALIZER PTH_MUTEX_INIT
@ -197,7 +197,7 @@ dummy_mutex_call_int (estream_mutex_t mutex)
/* Primitive system I/O. */
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
# define ESTREAM_SYS_READ do_pth_read
# define ESTREAM_SYS_WRITE do_pth_write
# define ESTREAM_SYS_YIELD() pth_yield (NULL)
@ -450,7 +450,7 @@ do_list_remove (estream_t stream, int with_locked_list)
* write, assuming that we do I/O on a plain file where the operation
* can't block.
*/
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
static int
do_pth_read (int fd, void *buffer, size_t size)
{
@ -476,7 +476,7 @@ do_pth_write (int fd, const void *buffer, size_t size)
return pth_write (fd, buffer, size);
# endif /* !HAVE_W32_SYSTEM*/
}
#endif /*HAVE_PTH*/
#endif /*HAVE_NPTH*/
@ -507,7 +507,7 @@ do_init (void)
if (!initialized)
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
if (!pth_init () && errno != EPERM )
return -1;
if (pth_mutex_init (&estream_list_lock))
@ -1033,7 +1033,7 @@ es_func_w32_read (void *cookie, void *buffer, size_t size)
{
do
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
/* Note: Our pth_read actually uses HANDLE! */
bytes_read = pth_read ((int)w32_cookie->hd, buffer, size);
#else
@ -1078,7 +1078,7 @@ es_func_w32_write (void *cookie, const void *buffer, size_t size)
{
do
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
/* Note: Our pth_write actually uses HANDLE! */
bytes_written = pth_write ((int)w32_cookie->hd, buffer, size);
#else
@ -2713,7 +2713,6 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
return stream;
}
/* This is the same as es_fopenmem but intializes the memory with a
copy of (DATA,DATALEN). The stream is initally set to the
@ -2744,10 +2743,6 @@ es_fopenmem_init (size_t memlimit, const char *ES__RESTRICT mode,
es_set_indicators (stream, 0, 0);
}
}
if (stream)
stream->intern->func_ioctl = es_func_mem_ioctl;
return stream;
}

View File

@ -35,13 +35,13 @@
#include <unistd.h>
#include <fcntl.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_PTH
#undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_NPTH
#undef USE_NPTH
#endif
#ifdef USE_GNU_PTH
#include <pth.h>
#ifdef USE_NPTH
#include <npth.h>
#endif
#include <sys/wait.h>
@ -388,11 +388,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
}
#ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork ();
#else
*pid = fork ();
#endif
if (*pid == (pid_t)(-1))
{
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
@ -454,11 +450,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
{
gpg_error_t err;
#ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork ();
#else
*pid = fork ();
#endif
if (*pid == (pid_t)(-1))
{
err = gpg_error_from_syserror ();
@ -491,16 +483,12 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
if (pid == (pid_t)(-1))
return gpg_error (GPG_ERR_INV_VALUE);
#ifdef USE_GNU_PTH
if (pth_waitpid)
i = pth_waitpid (pid, &status, hang? 0:WNOHANG);
else
#ifdef USE_NPTH
i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
#else
while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
&& errno == EINTR);
#endif
{
while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
&& errno == EINTR)
;
}
if (i == (pid_t)(-1))
{
@ -569,11 +557,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
if (access (pgmname, X_OK))
return gpg_error_from_syserror ();
#ifdef USE_GNU_PTH
pid = pth_fork? pth_fork () : fork ();
#else
pid = fork ();
#endif
if (pid == (pid_t)(-1))
{
log_error (_("error forking process: %s\n"), strerror (errno));

View File

@ -35,13 +35,13 @@
#include <unistd.h>
#include <fcntl.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_PTH
#undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_NPTH
#undef USE_NPTH
#endif
#ifdef USE_GNU_PTH
#include <pth.h>
#ifdef USE_NPTH
#include <npth.h>
#endif
#ifdef HAVE_STAT

View File

@ -35,13 +35,13 @@
#include <unistd.h>
#include <fcntl.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_PTH
#undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_NPTH
#undef USE_NPTH
#endif
#ifdef USE_GNU_PTH
#include <pth.h>
#ifdef USE_NPTH
#include <npth.h>
#endif
#ifdef HAVE_STAT
@ -73,7 +73,7 @@
#define handle_to_pid(a) ((int)(a))
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
/* The data passed to the feeder_thread. */
struct feeder_thread_parms
{
@ -171,9 +171,9 @@ leave:
xfree (parm);
return NULL;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
static void
feeder_onclose_notification (estream_t stream, void *opaque)
{
@ -182,7 +182,7 @@ feeder_onclose_notification (estream_t stream, void *opaque)
log_debug ("feeder(%p): received onclose note\n", parm->hd);
parm->stream_valid = 0;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
/* Fire up a thread to copy data between STREAM and a pipe's
descriptor FD. With DIRECTION set to true the copy takes place
@ -191,7 +191,7 @@ feeder_onclose_notification (estream_t stream, void *opaque)
static gpg_error_t
start_feeder (estream_t stream, HANDLE hd, int direction)
{
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
gpg_error_t err;
struct feeder_thread_parms *parm;
pth_attr_t tattr;

View File

@ -59,13 +59,13 @@
# include <netdb.h>
#endif /*!HAVE_W32_SYSTEM*/
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_PTH
# undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_NPTH
# undef USE_NPTH
#endif
#ifdef HAVE_PTH
# include <pth.h>
#ifdef HAVE_NPTH
# include <npth.h>
#endif
@ -105,7 +105,7 @@ struct srventry
#endif/*!USE_DNS_SRV*/
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
# define my_select(a,b,c,d,e) pth_select ((a), (b), (c), (d), (e))
# define my_connect(a,b,c) pth_connect ((a), (b), (c))
# define my_accept(a,b,c) pth_accept ((a), (b), (c))
@ -1887,15 +1887,15 @@ write_server (int sock, const char *data, size_t length)
nleft = length;
while (nleft > 0)
{
#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_PTH)
#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_NPTH)
nwritten = send (sock, data, nleft, 0);
if ( nwritten == SOCKET_ERROR )
{
log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ());
return gpg_error (GPG_ERR_NETWORK);
}
#else /*!HAVE_W32_SYSTEM || HAVE_PTH*/
# ifdef HAVE_PTH
#else /*!HAVE_W32_SYSTEM || HAVE_NPTH*/
# ifdef HAVE_NPTH
nwritten = pth_write (sock, data, nleft);
# else
nwritten = write (sock, data, nleft);
@ -1916,7 +1916,7 @@ write_server (int sock, const char *data, size_t length)
log_info ("network write failed: %s\n", strerror (errno));
return gpg_error_from_syserror ();
}
#endif /*!HAVE_W32_SYSTEM || HAVE_PTH*/
#endif /*!HAVE_W32_SYSTEM || HAVE_NPTH*/
nleft -= nwritten;
data += nwritten;
}
@ -1971,7 +1971,7 @@ cookie_read (void *cookie, void *buffer, size_t size)
{
do
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
nread = pth_read (c->sock->fd, buffer, size);
#elif defined(HAVE_W32_SYSTEM)
/* Under Windows we need to use recv for a socket. */

View File

@ -19,16 +19,16 @@
#include <config.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_PTH
#undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
#undef HAVE_NPTH
#undef USE_NPTH
#endif
#ifdef HAVE_W32_SYSTEM
#include <windows.h>
#endif
#ifdef HAVE_PTH
#include <pth.h>
#ifdef HAVE_NPTH
#include <npth.h>
#endif
#ifdef HAVE_W32CE_SYSTEM
# include <assuan.h> /* For _assuan_w32ce_finish_pipe. */
@ -87,7 +87,7 @@ init_common_subsystems (int *argcp, char ***argvp)
places. If we are building with PTH we let pth_init do it. We
can't do much on error so we ignore them. An error would anyway
later pop up if one of the socket functions is used. */
# ifdef HAVE_PTH
# ifdef HAVE_NPTH
pth_init ();
# else
{
@ -95,7 +95,7 @@ init_common_subsystems (int *argcp, char ***argvp)
WSAStartup (0x202, &wsadat);
}
# endif /*!HAVE_PTH*/
# endif /*!HAVE_NPTH*/
#endif
#ifdef HAVE_W32CE_SYSTEM

View File

@ -20,9 +20,9 @@
#include <config.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_PTH
# undef USE_GNU_PTH
#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
# undef HAVE_NPTH
# undef USE_NPTH
#endif
#include <stdio.h>
@ -46,8 +46,8 @@
# define WINVER 0x0500 /* Required for AllowSetForegroundWindow. */
# include <windows.h>
#endif
#ifdef HAVE_PTH
# include <pth.h>
#ifdef HAVE_NPTH
# include <npth.h>
#endif
#include <fcntl.h>
@ -259,7 +259,7 @@ check_permissions(const char *path,int extension,int checkonly)
void
gnupg_sleep (unsigned int seconds)
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
/* With Pth we force a regular sleep for seconds == 0 so that also
the process will give up its timeslot. */
if (!seconds)

View File

@ -51,6 +51,9 @@ NEED_LIBASSUAN_VERSION=2.0.3
NEED_KSBA_API=1
NEED_KSBA_VERSION=1.2.0
NEED_NPTH_API=1
NEED_NPTH_VERSION=0.0
PACKAGE=$PACKAGE_NAME
PACKAGE_GT=${PACKAGE_NAME}2
@ -70,7 +73,7 @@ have_gpg_error=no
have_libgcrypt=no
have_libassuan=no
have_ksba=no
have_pth=no
have_npth=no
have_libusb=no
have_adns=no
@ -505,10 +508,6 @@ AH_BOTTOM([
/* We always include support for the OpenPGP card. */
#define ENABLE_CARD_SUPPORT 1
/* We explicitly need to disable PTH's soft mapping as Debian
currently enables it by default for no reason. */
#define PTH_SYSCALL_SOFT 0
/* We want to use the libgcrypt provided memory allocation for
asprintf. */
#define _ESTREAM_PRINTF_REALLOC gcry_realloc
@ -821,22 +820,18 @@ AC_DEFINE_UNQUOTED(SHRED,
# Check whether the GNU Pth library is available
# Note, that we include a Pth emulation for W32.
#
if test "$have_w32_system" = yes; then
GNUPG_PATH_PTH([2.0.4])
else
GNUPG_PATH_PTH
fi
if test "$have_pth" = "yes"; then
AC_DEFINE(USE_GNU_PTH, 1,
[Defined if the GNU Portable Thread Library should be used])
AM_PATH_NPTH("$NEED_NPTH_API:$NEED_NPTH_VERSION",have_npth=yes,have_npth=no)
if test "$have_npth" = "yes"; then
AC_DEFINE(USE_NPTH, 1,
[Defined if the New Portable Thread Library should be used])
else
AC_MSG_WARN([[
***
*** To support concurrent access to the gpg-agent and the SCdaemon
*** we need the support of the GNU Portable Threads Library.
*** Download it from ftp://ftp.gnu.org/gnu/pth/
*** we need the support of the New Portable Threads Library.
*** Download it from FIXME
*** On a Debian GNU/Linux system you might want to try
*** apt-get install libpth-dev
*** apt-get install libnpth-dev
***]])
fi
@ -1500,7 +1495,7 @@ if test "$have_adns" = "yes"; then
fi
missing_pth=no
missing_npth=no
if test $have_ksba = no; then
build_gpgsm=no
build_scdaemon=no
@ -1508,19 +1503,19 @@ fi
build_agent_threaded=""
if test "$build_agent" = "yes"; then
if test $have_pth = no; then
if test $have_npth = no; then
build_agent_threaded="(not multi-threaded)"
missing_pth=yes
missing_npth=yes
fi
fi
build_scdaemon_extra=""
if test "$build_scdaemon" = "yes"; then
tmp=""
if test $have_pth = no; then
if test $have_npth = no; then
build_scdaemon_extra="not multi-threaded"
tmp=", "
missing_pth=yes
missing_npth=yes
fi
if test $have_libusb = no; then
build_scdaemon_extra="${tmp}without internal CCID driver"
@ -1652,18 +1647,18 @@ if test "$gnupg_have_ldap" = "no"; then
***]])
fi
fi
if test "$missing_pth" = "yes"; then
if test "$missing_npth" = "yes"; then
AC_MSG_NOTICE([[
***
*** It is now required to build with support for the
*** GNU Portable Threads Library (Pth). Please install this
*** New Portable Threads Library (NPth). Please install this
*** library first. The library is for example available at
*** ftp://ftp.gnu.org/gnu/pth/
*** FIXME
*** On a Debian GNU/Linux system you can install it using
*** apt-get install libpth-dev
*** To build GnuPG for Windows you need to use the W32PTH
*** apt-get install libnpth-dev
*** To build GnuPG for Windows you need to use the W32NPTH
*** package; available at:
*** ftp://ftp.g10code.com/g10code/w32pth/
*** ftp://ftp.g10code.com/g10code/w32npth/
***]])
die=yes
fi

View File

@ -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

View File

@ -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));
}

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -26,7 +26,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) $(LIBASSUAN_CFLAGS) $(PTH_CFLAGS)
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
g13_SOURCES = \
g13.c g13.h \
@ -43,5 +43,5 @@ g13_SOURCES = \
be-truecrypt.c be-truecrypt.h
g13_LDADD = $(libcommonpth) ../gl/libgnu.a \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)

View File

@ -24,7 +24,7 @@
#include <errno.h>
#include <time.h>
#include <assert.h>
#include <pth.h>
#include <npth.h>
#include "g13.h"
#include <assuan.h>
@ -163,7 +163,7 @@ struct writer_thread_parms
/* The thread started by start_writer. */
static void *
writer_thread (void *arg)
writer_thread_main (void *arg)
{
struct writer_thread_parms *parm = arg;
const char *buffer = parm->data;
@ -173,7 +173,7 @@ writer_thread (void *arg)
{
ssize_t nwritten;
nwritten = pth_write (parm->fd, buffer, length < 4096? length:4096);
nwritten = npth_write (parm->fd, buffer, length < 4096? length:4096);
if (nwritten < 0)
{
if (errno == EINTR)
@ -199,14 +199,15 @@ writer_thread (void *arg)
finished. */
static gpg_error_t
start_writer (int fd, const void *data, size_t datalen,
pth_t *r_tid, gpg_error_t *err_addr)
npth_t *r_thread, gpg_error_t *err_addr)
{
gpg_error_t err;
struct writer_thread_parms *parm;
pth_attr_t tattr;
pth_t tid;
npth_attr_t tattr;
npth_t thread;
int ret;
*r_tid = NULL;
memset (r_thread, '\0', sizeof (*r_thread));
*err_addr = 0;
parm = xtrymalloc (sizeof *parm);
@ -217,23 +218,22 @@ start_writer (int fd, const void *data, size_t datalen,
parm->datalen = datalen;
parm->err_addr = err_addr;
tattr = pth_attr_new ();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "fd-writer");
npth_attr_init (&tattr);
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
tid = pth_spawn (tattr, writer_thread, parm);
if (!tid)
ret = npth_create (&thread, &tattr, writer_thread_main, parm);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
}
else
{
npth_setname_np (thread, "fd-writer");
err = 0;
*r_tid = tid;
*r_thread = thread;
}
pth_attr_destroy (tattr);
npth_attr_destroy (&tattr);
return err;
}
@ -251,13 +251,13 @@ struct reader_thread_parms
/* The thread started by start_reader. */
static void *
reader_thread (void *arg)
reader_thread_main (void *arg)
{
struct reader_thread_parms *parm = arg;
char buffer[4096];
int nread;
while ( (nread = pth_read (parm->fd, buffer, sizeof buffer)) )
while ( (nread = npth_read (parm->fd, buffer, sizeof buffer)) )
{
if (nread < 0)
{
@ -282,14 +282,15 @@ reader_thread (void *arg)
is stored at R_TID. After the thread has finished an error from
the thread will be stored at ERR_ADDR. */
static gpg_error_t
start_reader (int fd, membuf_t *mb, pth_t *r_tid, gpg_error_t *err_addr)
start_reader (int fd, membuf_t *mb, npth_t *r_thread, gpg_error_t *err_addr)
{
gpg_error_t err;
struct reader_thread_parms *parm;
pth_attr_t tattr;
pth_t tid;
npth_attr_t tattr;
npth_t thread;
int ret;
*r_tid = NULL;
memset (r_thread, '\0', sizeof (*r_thread));
*err_addr = 0;
parm = xtrymalloc (sizeof *parm);
@ -299,23 +300,22 @@ start_reader (int fd, membuf_t *mb, pth_t *r_tid, gpg_error_t *err_addr)
parm->mb = mb;
parm->err_addr = err_addr;
tattr = pth_attr_new ();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "fd-reader");
npth_attr_init (&tattr);
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
tid = pth_spawn (tattr, reader_thread, parm);
if (!tid)
ret = npth_create (&thread, &tattr, reader_thread_main, parm);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
}
else
{
npth_setname_np (thread, "fd-reader");
err = 0;
*r_tid = tid;
*r_thread = thread;
}
pth_attr_destroy (tattr);
npth_attr_destroy (&tattr);
return err;
}
@ -335,12 +335,13 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
assuan_context_t ctx;
int outbound_fds[2] = { -1, -1 };
int inbound_fds[2] = { -1, -1 };
pth_t writer_tid = NULL;
pth_t reader_tid = NULL;
npth_t writer_thread;
npth_t reader_thread;
gpg_error_t writer_err, reader_err;
membuf_t reader_mb;
char line[ASSUAN_LINELENGTH];
strlist_t sl;
int ret;
*r_ciph = NULL;
*r_ciphlen = 0;
@ -367,7 +368,7 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
/* Start a writer thread to feed the INPUT command of the server. */
err = start_writer (outbound_fds[1], plain, plainlen,
&writer_tid, &writer_err);
&writer_thread, &writer_err);
if (err)
return err;
outbound_fds[1] = -1; /* The thread owns the FD now. */
@ -375,7 +376,7 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
/* Start a reader thread to eat from the OUTPUT command of the
server. */
err = start_reader (inbound_fds[0], &reader_mb,
&reader_tid, &reader_err);
&reader_thread, &reader_err);
if (err)
return err;
outbound_fds[0] = -1; /* The thread owns the FD now. */
@ -402,13 +403,15 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
}
/* Wait for reader and return the data. */
if (!pth_join (reader_tid, NULL))
ret = npth_join (reader_thread, NULL);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
goto leave;
}
reader_tid = NULL;
/* FIXME: Not really valid, as npth_t is an opaque type. */
memset (&reader_thread, '\0', sizeof (reader_thread));
if (reader_err)
{
err = reader_err;
@ -417,13 +420,14 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
}
/* Wait for the writer to catch a writer error. */
if (!pth_join (writer_tid, NULL))
ret = npth_join (writer_thread, NULL);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
goto leave;
}
writer_tid = NULL;
memset (&writer_thread, '\0', sizeof (writer_thread));
if (writer_err)
{
err = writer_err;
@ -442,16 +446,11 @@ gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
}
leave:
if (reader_tid)
{
pth_cancel (reader_tid);
pth_join (reader_tid, NULL);
}
if (writer_tid)
{
pth_cancel (writer_tid);
pth_join (writer_tid, NULL);
}
/* FIXME: Not valid, as npth_t is an opaque type. */
if (reader_thread)
npth_detach (reader_thread);
if (writer_thread)
npth_detach (writer_thread);
if (outbound_fds[0] != -1)
close (outbound_fds[0]);
if (outbound_fds[1] != -1)
@ -479,10 +478,11 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
assuan_context_t ctx;
int outbound_fds[2] = { -1, -1 };
int inbound_fds[2] = { -1, -1 };
pth_t writer_tid = NULL;
pth_t reader_tid = NULL;
npth_t writer_thread;
npth_t reader_thread;
gpg_error_t writer_err, reader_err;
membuf_t reader_mb;
int ret;
*r_plain = NULL;
*r_plainlen = 0;
@ -509,7 +509,7 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
/* Start a writer thread to feed the INPUT command of the server. */
err = start_writer (outbound_fds[1], ciph, ciphlen,
&writer_tid, &writer_err);
&writer_thread, &writer_err);
if (err)
return err;
outbound_fds[1] = -1; /* The thread owns the FD now. */
@ -517,7 +517,7 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
/* Start a reader thread to eat from the OUTPUT command of the
server. */
err = start_reader (inbound_fds[0], &reader_mb,
&reader_tid, &reader_err);
&reader_thread, &reader_err);
if (err)
return err;
outbound_fds[0] = -1; /* The thread owns the FD now. */
@ -532,13 +532,14 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
}
/* Wait for reader and return the data. */
if (!pth_join (reader_tid, NULL))
ret = npth_join (reader_thread, NULL);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
goto leave;
}
reader_tid = NULL;
memset (&reader_thread, '\0', sizeof (reader_thread));
if (reader_err)
{
err = reader_err;
@ -547,13 +548,14 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
}
/* Wait for the writer to catch a writer error. */
if (!pth_join (writer_tid, NULL))
ret = npth_join (writer_thread, NULL);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
goto leave;
}
writer_tid = NULL;
memset (&writer_thread, '\0', sizeof (writer_thread));
if (writer_err)
{
err = writer_err;
@ -572,16 +574,10 @@ gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
}
leave:
if (reader_tid)
{
pth_cancel (reader_tid);
pth_join (reader_tid, NULL);
}
if (writer_tid)
{
pth_cancel (writer_tid);
pth_join (writer_tid, NULL);
}
if (reader_thread)
npth_detach (reader_thread);
if (writer_thread)
npth_detach (writer_thread);
if (outbound_fds[0] != -1)
close (outbound_fds[0]);
if (outbound_fds[1] != -1)

181
g13/g13.c
View File

@ -25,7 +25,7 @@
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <pth.h>
#include <npth.h>
#include "g13.h"
@ -188,7 +188,7 @@ static unsigned int debug_value;
static int shutdown_pending;
/* The thread id of the idle task. */
static pth_t idle_task_tid;
static npth_t idle_task_thread;
@ -199,26 +199,11 @@ static void emergency_cleanup (void);
static void start_idle_task (void);
static void join_idle_task (void);
/* Begin NPth wrapper functions. */
ASSUAN_SYSTEM_NPTH_IMPL;
/* Begin Pth wrapper functions. */
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
/* End Pth wrapper functions. */
static const char *
my_strusage( int level )
{
@ -336,7 +321,7 @@ main ( int argc, char **argv)
ARGPARSE_ARGS pargs;
int orig_argc;
char **orig_argv;
gpg_error_t err;
gpg_error_t err = 0;
const char *fname;
int may_coredump;
FILE *configfp = NULL;
@ -368,18 +353,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 Libgcrypt is suitable. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
@ -444,7 +418,7 @@ main ( int argc, char **argv)
/* Prepare libassuan. */
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
assuan_set_system_hooks (ASSUAN_SYSTEM_PTH);
assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
setup_libassuan_logging (&opt.debug);
/* Setup a default control structure for command line mode. */
@ -795,7 +769,7 @@ g13_init_default_ctrl (struct server_control_s *ctrl)
/* This function is called for each signal we catch. It is run in the
main context or the one of a Pth thread and thus it is not
main context or the one of a NPth thread and thus it is not
restricted in what it may do. */
static void
handle_signal (int signo)
@ -862,29 +836,28 @@ handle_tick (void)
static void *
idle_task (void *dummy_arg)
{
sigset_t sigs; /* The set of signals we want to catch. */
pth_event_t ev; /* The main event to catch signals. */
pth_event_t time_ev; /* The time event. */
int signo; /* The number of a raised signal is stored here. */
int saved_errno;
struct timespec abstime;
struct timespec curtime;
struct timespec timeout;
int ret;
(void)dummy_arg;
/* Create the event to catch the signals. */
#ifndef HAVE_W32_SYSTEM
sigemptyset (&sigs );
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
#else
sigs = 0;
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
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
/* The time event neds to computed n tghe fly. */
time_ev = NULL;
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
for (;;)
{
@ -897,41 +870,43 @@ idle_task (void *dummy_arg)
break; /* ready */
}
/* 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;
npth_clock_gettime (&curtime);
if (!(npth_timercmp (&curtime, &abstime, <)))
{
/* Timeout. */
handle_tick ();
npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
}
npth_timersub (&abstime, &curtime, &timeout);
nexttick = pth_timeout (TIMERTICK_INTERVAL_SEC, 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);
}
#ifndef HAVE_W32_SYSTEM
ret = npth_pselect (0, NULL, NULL, NULL, &timeout, npth_sigev_sigmask());
saved_errno = errno;
pth_event_concat (ev, time_ev, NULL);
pth_wait (ev);
pth_event_isolate (time_ev);
while (npth_sigev_get_pending(&signo))
handle_signal (signo);
#else
ret = npth_eselect (0, NULL, NULL, NULL, &timeout, NULL, NULL);
saved_errno = errno;
#endif
if (pth_event_occurred (ev))
{
handle_signal (signo);
}
if (ret == -1 && saved_errno != EINTR)
{
log_error (_("npth_pselect failed: %s - waiting 1s\n"),
strerror (saved_errno));
npth_sleep (1);
continue;
}
if (time_ev && pth_event_occurred (time_ev))
{
pth_event_free (time_ev, PTH_FREE_ALL);
time_ev = NULL;
handle_tick ();
}
if (ret <= 0)
/* Interrupt or timeout. Will be handled when calculating the
next timeout. */
continue;
/* Here one would add processing of file descriptors. */
}
pth_event_free (ev, PTH_FREE_ALL);
if (time_ev)
pth_event_free (time_ev, PTH_FREE_ALL);
log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
return NULL;
}
@ -941,23 +916,36 @@ idle_task (void *dummy_arg)
static void
start_idle_task (void)
{
pth_attr_t tattr;
pth_t tid;
npth_attr_t tattr;
npth_t thread;
sigset_t sigs; /* The set of signals we want to catch. */
int err;
tattr = pth_attr_new ();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, "idle-task");
#ifndef HAVE_W32_SYSTEM
/* These signals should always go to the idle task, so they need to
be blocked everywhere else. We assume start_idle_task is called
from the main thread before any other threads are created. */
sigemptyset (&sigs);
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
npth_sigmask (SIG_BLOCK, &sigs, NULL);
#endif
tid = pth_spawn (tattr, idle_task, NULL);
if (!tid)
npth_attr_init (&tattr);
npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
err = npth_create (&thread, &tattr, idle_task, NULL);
if (err)
{
log_fatal ("error starting idle task: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
log_fatal ("error starting idle task: %s\n", strerror (err));
return; /*NOTREACHED*/
}
idle_task_tid = tid;
pth_attr_destroy (tattr);
npth_setname_np (thread, "idle-task");
idle_task_thread = thread;
npth_attr_destroy (&tattr);
}
@ -965,10 +953,15 @@ start_idle_task (void)
static void
join_idle_task (void)
{
if (idle_task_tid)
int err;
/* FIXME: This assumes that a valid pthread_t is non-null. That is
not guaranteed. */
if (idle_task_thread)
{
if (!pth_join (idle_task_tid, NULL))
err = npth_join (idle_task_thread, NULL);
if (err)
log_error ("waiting for idle task thread failed: %s\n",
gpg_strerror (gpg_error_from_syserror ()));
strerror (err));
}
}

View File

@ -24,7 +24,7 @@
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <pth.h>
#include <npth.h>
#include "g13.h"
#include "i18n.h"
@ -40,7 +40,7 @@ struct runner_s
unsigned int identifier; /* The runner identifier. */
int spawned; /* True if runner_spawn has been called. */
pth_t threadid; /* The TID of the runner thread. */
npth_t thread; /* The TID of the runner thread. */
runner_t next_running; /* Builds a list of all running threads. */
int canceled; /* Set if a cancel has already been send once. */
@ -85,7 +85,7 @@ writen (int fd, const void *buf, size_t nbytes)
while (nleft > 0)
{
nwritten = pth_write (fd, buf, nleft);
nwritten = npth_write (fd, buf, nleft);
if (nwritten < 0)
{
if (errno == EINTR)
@ -408,8 +408,9 @@ gpg_error_t
runner_spawn (runner_t runner)
{
gpg_error_t err;
pth_attr_t tattr;
pth_t tid;
npth_attr_t tattr;
npth_t thread;
int ret;
if (check_already_spawned (runner, "runner_spawn"))
return gpg_error (GPG_ERR_BUG);
@ -433,26 +434,26 @@ runner_spawn (runner_t runner)
runner->in_fd = -1; /* Now owned by status_fp. */
}
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, runner->name);
npth_attr_init (&tattr);
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
tid = pth_spawn (tattr, runner_thread, runner);
if (!tid)
ret = npth_create (&thread, &tattr, runner_thread, runner);
if (ret)
{
err = gpg_error_from_syserror ();
err = gpg_error_from_errno (ret);
log_error ("error spawning runner thread: %s\n", gpg_strerror (err));
return err;
}
npth_setname_np (thread, runner->name);
/* The scheduler has not yet kicked in, thus we can safely set the
spawned flag and the tid. */
runner->spawned = 1;
runner->threadid = tid;
runner->thread = thread;
runner->next_running = running_threads;
running_threads = runner;
pth_attr_destroy (tattr);
npth_attr_destroy (&tattr);
/* The runner thread is now runnable. */

89
m4/npth.m4 Normal file
View File

@ -0,0 +1,89 @@
# npth.m4 - autoconf macro to detect NPTH.
# Copyright (C) 2002, 2003, 2004, 2011 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AC_DEFUN([_AM_PATH_NPTH_CONFIG],
[ AC_ARG_WITH(npth-prefix,
AC_HELP_STRING([--with-npth-prefix=PFX],
[prefix where NPTH is installed (optional)]),
npth_config_prefix="$withval", npth_config_prefix="")
if test "x$npth_config_prefix" != x ; then
NPTH_CONFIG="$npth_config_prefix/bin/npth-config"
fi
AC_PATH_PROG(NPTH_CONFIG, npth-config, no)
if test "$NPTH_CONFIG" != "no" ; then
npth_version=`$NPTH_CONFIG --version`
fi
npth_version_major=`echo $npth_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
npth_version_minor=`echo $npth_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
])
dnl AM_PATH_NPTH([MINIMUM-VERSION,
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
dnl Test for libnpth and define NPTH_CFLAGS and NPTH_LIBS.
dnl
AC_DEFUN([AM_PATH_NPTH],
[ AC_REQUIRE([_AM_PATH_NPTH_CONFIG])dnl
tmp=ifelse([$1], ,1:0.0,$1)
if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
req_npth_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'`
min_npth_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
else
req_npth_api=0
min_npth_version="$tmp"
fi
AC_MSG_CHECKING(for NPTH - version >= $min_npth_version)
ok=no
if test "$NPTH_CONFIG" != "no" ; then
req_major=`echo $min_npth_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
req_minor=`echo $min_npth_version | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
if test "$npth_version_major" -gt "$req_major"; then
ok=yes
else
if test "$npth_version_major" -eq "$req_major"; then
if test "$npth_version_minor" -ge "$req_minor"; then
ok=yes
fi
fi
fi
fi
if test $ok = yes; then
# If we have a recent NPTH, we should also check that the
# API is compatible.
if test "$req_npth_api" -gt 0 ; then
tmp=`$NPTH_CONFIG --api-version 2>/dev/null || echo 0`
if test "$tmp" -gt 0 ; then
if test "$req_npth_api" -ne "$tmp" ; then
ok=no
fi
fi
fi
fi
if test $ok = yes; then
NPTH_CFLAGS=`$NPTH_CONFIG --cflags`
NPTH_LIBS=`$NPTH_CONFIG --libs`
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
NPTH_CFLAGS=""
NPTH_LIBS=""
AC_MSG_RESULT(no)
ifelse([$3], , :, [$3])
fi
AC_SUBST(NPTH_CFLAGS)
AC_SUBST(NPTH_LIBS)
])

View File

@ -29,7 +29,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) $(PTH_CFLAGS)
$(KSBA_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
card_apps = app-openpgp.c app-nks.c app-dinsig.c app-p15.c app-geldkarte.c
@ -45,7 +45,7 @@ scdaemon_SOURCES = \
scdaemon_LDADD = $(libcommonpth) ../gl/libgnu.a \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
$(LIBUSB_LIBS) $(GPG_ERROR_LIBS) \
$(LIBINTL) $(DL_LIBS) $(NETLIBS) $(LIBICONV)
@ -63,7 +63,7 @@ scdaemon_LDADD = $(libcommonpth) ../gl/libgnu.a \
#sc_copykeys_LDADD = \
# ../jnlib/libjnlib.a ../common/libcommon.a \
# ../common/libsimple-pwquery.a \
# $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(PTH_LIBS) \
# $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
# $(LIBUSB_LIBS) \
# -lgpg-error @LIBINTL@ @DL_LIBS@
#

View File

@ -19,7 +19,7 @@
*/
/* NOTE: This module is also used by other software, thus the use of
the macro USE_GNU_PTH is mandatory. For GnuPG this macro is
the macro USE_NPTH is mandatory. For GnuPG this macro is
guaranteed to be defined true. */
#include <config.h>
@ -29,10 +29,10 @@
#include <string.h>
#include <assert.h>
#include <signal.h>
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
# include <unistd.h>
# include <fcntl.h>
# include <pth.h>
# include <npth.h>
#endif
@ -67,7 +67,7 @@
/* Due to conflicting use of threading libraries we usually can't link
against libpcsclite. Instead we use a wrapper program. */
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
#if !defined(HAVE_W32_SYSTEM) && !defined(__CYGWIN__)
#define NEED_PCSC_WRAPPER 1
#endif
@ -144,9 +144,9 @@ struct reader_table_s {
not yet been read; i.e. the card is not
ready for use. */
unsigned int change_counter;
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
int lock_initialized;
pth_mutex_t lock;
npth_mutex_t lock;
#endif
};
typedef struct reader_table_s *reader_table_t;
@ -352,6 +352,7 @@ static int
new_reader_slot (void)
{
int i, reader = -1;
int err;
for (i=0; i < MAX_READER; i++)
{
@ -363,17 +364,18 @@ new_reader_slot (void)
log_error ("new_reader_slot: out of slots\n");
return -1;
}
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
if (!reader_table[reader].lock_initialized)
{
if (!pth_mutex_init (&reader_table[reader].lock))
err = npth_mutex_init (&reader_table[reader].lock, NULL);
if (err)
{
log_error ("error initializing mutex: %s\n", strerror (errno));
log_error ("error initializing mutex: %s\n", strerror (err));
return -1;
}
reader_table[reader].lock_initialized = 1;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
reader_table[reader].connect_card = NULL;
reader_table[reader].disconnect_card = NULL;
reader_table[reader].close_reader = NULL;
@ -698,8 +700,8 @@ writen (int fd, const void *buf, size_t nbytes)
while (nleft > 0)
{
#ifdef USE_GNU_PTH
nwritten = pth_write (fd, buf, nleft);
#ifdef USE_NPTH
nwritten = npth_write (fd, buf, nleft);
#else
nwritten = write (fd, buf, nleft);
#endif
@ -724,11 +726,11 @@ readn (int fd, void *buf, size_t buflen, size_t *nread)
while (nleft > 0)
{
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
# ifdef HAVE_W32_SYSTEM
# error Cannot use pth_read here because it expects a system HANDLE.
# error Cannot use npth_read here because it expects a system HANDLE.
# endif
n = pth_read (fd, buf, nleft);
n = npth_read (fd, buf, nleft);
#else
n = read (fd, buf, nleft);
#endif
@ -1874,8 +1876,8 @@ open_pcsc_reader_wrapped (const char *portstr)
slotp->pcsc.rsp_fd = rp[0];
/* Wait for the intermediate child to terminate. */
#ifdef USE_GNU_PTH
#define WAIT pth_waitpid
#ifdef USE_NPTH
#define WAIT npth_waitpid
#else
#define WAIT waitpid
#endif
@ -2117,6 +2119,8 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify, len, result, &resultlen);
xfree (pin_verify);
if (sw || resultlen < 2)
return sw? sw : SW_HOST_INCOMPLETE_CARD_RESPONSE;
sw = (result[resultlen-2] << 8) | result[resultlen-1];
{
log_error ("control_pcsc failed: %d\n", sw);
return sw? sw: SW_HOST_INCOMPLETE_CARD_RESPONSE;
@ -2749,38 +2753,47 @@ open_rapdu_reader (int portno,
static int
lock_slot (int slot)
{
#ifdef USE_GNU_PTH
if (!pth_mutex_acquire (&reader_table[slot].lock, 0, NULL))
#ifdef USE_NPTH
int err;
err = npth_mutex_lock (&reader_table[slot].lock);
if (err)
{
log_error ("failed to acquire apdu lock: %s\n", strerror (errno));
log_error ("failed to acquire apdu lock: %s\n", strerror (err));
return SW_HOST_LOCKING_FAILED;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
return 0;
}
static int
trylock_slot (int slot)
{
#ifdef USE_GNU_PTH
if (!pth_mutex_acquire (&reader_table[slot].lock, TRUE, NULL))
#ifdef USE_NPTH
int err;
err = npth_mutex_trylock (&reader_table[slot].lock);
if (err == EBUSY)
return SW_HOST_BUSY;
else if (err)
{
if (errno == EBUSY)
return SW_HOST_BUSY;
log_error ("failed to acquire apdu lock: %s\n", strerror (errno));
log_error ("failed to acquire apdu lock: %s\n", strerror (err));
return SW_HOST_LOCKING_FAILED;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
return 0;
}
static void
unlock_slot (int slot)
{
#ifdef USE_GNU_PTH
if (!pth_mutex_release (&reader_table[slot].lock))
#ifdef USE_NPTH
int err;
err = npth_mutex_unlock (&reader_table[slot].lock);
if (err)
log_error ("failed to release apdu lock: %s\n", strerror (errno));
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
}

View File

@ -22,7 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pth.h>
#include <npth.h>
#include "scdaemon.h"
#include "app-common.h"
@ -37,7 +37,7 @@
static struct
{
int initialized;
pth_mutex_t lock;
npth_mutex_t lock;
app_t app; /* Application context in use or NULL. */
app_t last_app; /* Last application object used as this slot or NULL. */
} lock_table[10];
@ -72,30 +72,30 @@ print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
static gpg_error_t
lock_reader (int slot, ctrl_t ctrl)
{
gpg_error_t err;
int res;
if (slot < 0 || slot >= DIM (lock_table))
return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT);
if (!lock_table[slot].initialized)
{
if (!pth_mutex_init (&lock_table[slot].lock))
res = npth_mutex_init (&lock_table[slot].lock, NULL);
if (res)
{
err = gpg_error_from_syserror ();
log_error ("error initializing mutex: %s\n", strerror (errno));
return err;
log_error ("error initializing mutex: %s\n", strerror (res));
return gpg_error_from_errno (res);
}
lock_table[slot].initialized = 1;
lock_table[slot].app = NULL;
lock_table[slot].last_app = NULL;
}
if (!pth_mutex_acquire (&lock_table[slot].lock, 0, NULL))
res = npth_mutex_lock (&lock_table[slot].lock);
if (res)
{
err = gpg_error_from_syserror ();
log_error ("failed to acquire APP lock for slot %d: %s\n",
slot, strerror (errno));
return err;
slot, strerror (res));
return gpg_error_from_errno (res);
}
apdu_set_progress_cb (slot, print_progress_line, ctrl);
@ -107,32 +107,18 @@ lock_reader (int slot, ctrl_t ctrl)
static void
unlock_reader (int slot)
{
int res;
if (slot < 0 || slot >= DIM (lock_table)
|| !lock_table[slot].initialized)
log_bug ("unlock_reader called for invalid slot %d\n", slot);
apdu_set_progress_cb (slot, NULL, NULL);
if (!pth_mutex_release (&lock_table[slot].lock))
res = npth_mutex_unlock (&lock_table[slot].lock);
if (res)
log_error ("failed to release APP lock for slot %d: %s\n",
slot, strerror (errno));
}
static void
dump_mutex_state (pth_mutex_t *m)
{
#ifdef _W32_PTH_H
(void)m;
log_printf ("unknown under W32");
#else
if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
log_printf ("not_initialized");
else if (!(m->mx_state & PTH_MUTEX_LOCKED))
log_printf ("not_locked");
else
log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
#endif
slot, strerror (res));
}
@ -146,8 +132,7 @@ app_dump_state (void)
for (slot=0; slot < DIM (lock_table); slot++)
if (lock_table[slot].initialized)
{
log_info ("app_dump_state: slot=%d lock=", slot);
dump_mutex_state (&lock_table[slot].lock);
log_info ("app_dump_state: slot=%d", slot);
if (lock_table[slot].app)
{
log_printf (" app=%p", lock_table[slot].app);

View File

@ -85,9 +85,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_PTH
# include <pth.h>
#endif /*HAVE_PTH*/
#ifdef HAVE_NPTH
# include <npth.h>
#endif /*HAVE_NPTH*/
#include <usb.h>
@ -328,7 +328,7 @@ set_msg_len (unsigned char *msg, unsigned int length)
static void
my_sleep (int seconds)
{
#ifdef HAVE_PTH
#ifdef HAVE_NPTH
/* With Pth we also call the standard sleep(0) so that the process
may give up its timeslot. */
if (!seconds)

View File

@ -26,8 +26,8 @@
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#ifdef USE_GNU_PTH
# include <pth.h>
#ifdef USE_NPTH
# include <npth.h>
#endif
#include "scdaemon.h"
@ -156,7 +156,7 @@ static struct server_local_s *locked_session;
/* While doing a reset we need to make sure that the ticker does not
call scd_update_reader_status_file while we are using it. */
static pth_mutex_t status_file_update_lock;
static npth_mutex_t status_file_update_lock;
/*-- Local prototypes --*/
@ -173,10 +173,12 @@ void
initialize_module_command (void)
{
static int initialized;
int err;
if (!initialized)
{
if (pth_mutex_init (&status_file_update_lock))
err = npth_mutex_init (&status_file_update_lock, NULL);
if (!err)
initialized = 1;
}
}
@ -304,6 +306,7 @@ do_reset (ctrl_t ctrl, int send_reset)
{
int vrdr = ctrl->server_local->vreader_idx;
int slot;
int err;
if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table))))
BUG ();
@ -360,7 +363,8 @@ do_reset (ctrl_t ctrl, int send_reset)
try to update the file. Calling update_reader_status_file is
required to get hold of the new status of the card in the vreader
table. */
if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
err = npth_mutex_lock (&status_file_update_lock);
if (err)
{
log_error ("failed to acquire status_file_update lock\n");
ctrl->server_local->vreader_idx = -1;
@ -368,8 +372,10 @@ do_reset (ctrl_t ctrl, int send_reset)
}
update_reader_status_file (0); /* Update slot status table. */
update_card_removed (vrdr, 0); /* Clear card_removed flag. */
if (!pth_mutex_release (&status_file_update_lock))
log_error ("failed to release status_file_update lock\n");
err = npth_mutex_unlock (&status_file_update_lock);
if (err)
log_error ("failed to release status_file_update lock: %s\n",
strerror (err));
/* Do this last, so that the update_card_removed above does its job. */
ctrl->server_local->vreader_idx = -1;
@ -1597,18 +1603,18 @@ cmd_lock (assuan_context_t ctx, char *line)
else
locked_session = ctrl->server_local;
#ifdef USE_GNU_PTH
#ifdef USE_NPTH
if (rc && has_option (line, "--wait"))
{
rc = 0;
pth_sleep (1); /* Better implement an event mechanism. However,
for card operations this should be
sufficient. */
npth_sleep (1); /* Better implement an event mechanism. However,
for card operations this should be
sufficient. */
/* FIXME: Need to check that the connection is still alive.
This can be done by issuing status messages. */
goto retry;
}
#endif /*USE_GNU_PTH*/
#endif /*USE_NPTH*/
if (rc)
log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
@ -2395,9 +2401,13 @@ update_reader_status_file (int set_card_removed_flag)
void
scd_update_reader_status_file (void)
{
if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
int err;
err = npth_mutex_lock (&status_file_update_lock);
if (err)
return; /* locked - give up. */
update_reader_status_file (1);
if (!pth_mutex_release (&status_file_update_lock))
log_error ("failed to release status_file_update lock\n");
err = npth_mutex_unlock (&status_file_update_lock);
if (err)
log_error ("failed to release status_file_update lock: %s\n",
strerror (err));
}

View File

@ -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,18 +269,18 @@ 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
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
flags are propagated to the subsystems. With LEVEL set, a specific
set of debug flags is set; thus overriding all flags already
@ -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);
ret = npth_attr_init(&tattr);
/* FIXME: Check error. */
npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
#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);
#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;
if (ret == -1)
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 && 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);
}

View File

@ -94,7 +94,7 @@ gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c
# common sucks in gpg-error, will they, nil they (some compilers
# do not eliminate the supposed-to-be-unused-inline-functions).
gpgconf_LDADD = $(maybe_commonpth_libs) $(opt_libassuan_libs) \
$(LIBINTL) $(GPG_ERROR_LIBS) $(PTH_LIBS) $(NETLIBS) \
$(LIBINTL) $(GPG_ERROR_LIBS) $(NPTH_LIBS) $(NETLIBS) \
$(LIBICONV) $(W32SOCKLIBS)
gpgconf_LDFLAGS = $(extra_bin_ldflags)
@ -112,7 +112,7 @@ watchgnupg_LDADD = $(NETLIBS)
gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c
# FIXME: remove PTH_LIBS (why do we need them at all?)
gpg_connect_agent_LDADD = ../common/libgpgrl.a $(common_libs) \
$(LIBASSUAN_LIBS) $(PTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \
$(LIBREADLINE) $(LIBINTL) $(NETLIBS) $(LIBICONV)
if !HAVE_W32CE_SYSTEM