Make dirmngr more battery friendly.

Similar to gpg-agent, dirmngr's wait timeouts are now synced to the
full second.  Increased ldap helper thread timeout to 2 seconds.

Nuked some white spaces.
This commit is contained in:
Werner Koch 2011-01-25 11:26:01 +01:00
parent 62842cc7fe
commit 2b81258b2b
4 changed files with 198 additions and 123 deletions

View File

@ -1,3 +1,11 @@
2011-01-25 Werner Koch <wk@g10code.com>
* dirmngr.c (handle_connections): Rewrite loop to use pth-select
so to sync timeouts to the full second.
(pth_thread_id): New.
* ldap-wrapper.c (ldap_wrapper_thread): Sync to the full second.
Increate pth_wait timeout from 1 to 2 seconds.
2011-01-20 Werner Koch <wk@g10code.com>
* server.c (release_ctrl_keyservers): New.

View File

@ -1,6 +1,6 @@
/* dirmngr.c - LDAP access
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010 g10 Code GmbH
* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010, 2011 g10 Code GmbH
*
* This file is part of DirMngr.
*
@ -286,6 +286,13 @@ static int fixed_gcry_pth_init (void)
return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0;
}
#ifndef PTH_HAVE_PTH_THREAD_ID
static unsigned long pth_thread_id (void)
{
return (unsigned long)pth_self ();
}
#endif
static const char *
my_strusage( int level )
{
@ -1701,13 +1708,16 @@ static void *
start_connection_thread (void *arg)
{
union int_and_ptr_u argval;
assuan_fd_t fd;
gnupg_fd_t fd;
argval.aptr = arg;
fd = argval.afd;
if (check_nonce (fd, &socket_nonce))
{
log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ());
return NULL;
}
#ifndef HAVE_W32_SYSTEM
pth_key_setdata (my_tlskey_current_fd, argval.aptr);
@ -1738,11 +1748,13 @@ handle_connections (assuan_fd_t listen_fd)
{
pth_attr_t tattr;
pth_event_t ev, time_ev;
sigset_t sigs, oldsigs;
sigset_t sigs;
int signo;
struct sockaddr_un paddr;
socklen_t plen = sizeof( paddr );
assuan_fd_t fd;
gnupg_fd_t fd;
int nfd, ret;
fd_set fdset, read_fdset;
tattr = pth_attr_new();
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
@ -1750,46 +1762,89 @@ handle_connections (assuan_fd_t listen_fd)
pth_attr_set (tattr, PTH_ATTR_NAME, "dirmngr");
#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 );
sigaddset (&sigs, SIGHUP);
sigaddset (&sigs, SIGUSR1);
sigaddset (&sigs, SIGUSR2);
sigaddset (&sigs, SIGINT);
sigaddset (&sigs, SIGTERM);
{
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);
#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
to full second. */
FD_ZERO (&fdset);
FD_SET (FD2INT (listen_fd), &fdset);
nfd = FD2INT (listen_fd);
/* Main loop. */
for (;;)
{
/* Make sure that our signals are not blocked. */
pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
/* Shutdown test. */
if (shutdown_pending)
{
if (!active_connections)
break; /* ready */
/* Do not accept anymore connections but wait for existing
connections to terminate. */
signo = 0;
pth_wait (ev);
if (pth_event_occurred (ev) && signo)
handle_signal (signo);
continue;
/* Do not accept new connections but keep on running the
loop to cope with the timer events. */
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)
time_ev = pth_event (PTH_EVENT_TIME,
pth_timeout (TIMERTICK_INTERVAL, 0));
{
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);
fd = (assuan_fd_t) pth_accept_ev (FD2INT (listen_fd), (struct sockaddr *)&paddr, &plen, ev);
ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev);
if (time_ev)
pth_event_isolate (time_ev);
if (fd == ASSUAN_INVALID_FD)
if (ret == -1)
{
if (pth_event_occurred (ev)
|| (time_ev && pth_event_occurred (time_ev)) )
@ -1804,7 +1859,8 @@ handle_connections (assuan_fd_t listen_fd)
}
continue;
}
log_error (_("accept failed: %s - waiting 1s\n"), strerror (errno));
log_error (_("pth_select failed: %s - waiting 1s\n"),
strerror (errno));
pth_sleep (1);
continue;
}
@ -1825,23 +1881,36 @@ handle_connections (assuan_fd_t listen_fd)
/* 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, &oldsigs);
pth_sigmask (SIG_BLOCK, &sigs, NULL);
/* Create thread to handle this connection. */
if (!shutdown_pending && FD_ISSET (FD2INT (listen_fd), &read_fdset))
{
plen = sizeof paddr;
fd = INT2FD (pth_accept (FD2INT(listen_fd),
(struct sockaddr *)&paddr, &plen));
if (fd == GNUPG_INVALID_FD)
{
log_error ("accept failed: %s\n", strerror (errno));
}
else
{
char threadname[50];
union int_and_ptr_u argval;
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))
{
log_error (_("error spawning connection handler: %s\n"),
log_error ("error spawning connection handler: %s\n",
strerror (errno) );
assuan_sock_close (fd);
}
}
/* Restore the signal mask. */
pth_sigmask (SIG_SETMASK, &oldsigs, NULL);
fd = GNUPG_INVALID_FD;
}
}
pth_event_free (ev, PTH_FREE_ALL);

View File

@ -269,8 +269,17 @@ ldap_wrapper_thread (void *dummy)
{
pth_event_t timeout_ev;
int any_action = 0;
pth_time_t nexttick;
timeout_ev = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0));
/* 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)
{
log_error (_("pth_event failed: %s\n"), strerror (errno));

View File

@ -1,11 +0,0 @@
/^"POT-Creation-Date: .*"$/{
x
s/P/P/
ta
g
d
bb
:a
x
:b
}