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