mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
kbx: Have threads monitoring socket takeover and homedir if no inotify.
* kbx/keyboxd.c (CHECK_PROBLEMS_INTERVAL): New. (have_homedir_inotify): Remove the global. [HAVE_W32_SYSTEM] (create_an_event): New. (handle_tick): Remove. (handle_signal): Add handling SIGCONT. (keyboxd_kick_the_loop): New. (handle_connections): Spawn check_own_socket_thread and check_others_thread if no inotify. (check_own_socket_thread, check_others_thread): New. -- This change follows the change of gpg-agent. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
6ddaf2be9f
commit
ccfbb9ebdf
350
kbx/keyboxd.c
350
kbx/keyboxd.c
@ -144,14 +144,13 @@ static struct debug_flags_s debug_flags [] =
|
|||||||
{ 77, NULL } /* 77 := Do not exit on "help" or "?". */
|
{ 77, NULL } /* 77 := Do not exit on "help" or "?". */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The timer tick used for housekeeping stuff. Note that on Windows
|
/* CHECK_OWN_SOCKET_INTERVAL defines how often we check our own socket
|
||||||
* we use a SetWaitableTimer seems to signal earlier than about 2
|
* in standard socket mode. If that value is 0 we don't check at all.
|
||||||
* seconds. Thus we use 4 seconds on all platforms.
|
* Values is in seconds. */
|
||||||
* CHECK_OWN_SOCKET_INTERVAL defines how often we check
|
#define CHECK_OWN_SOCKET_INTERVAL (60)
|
||||||
* our own socket in standard socket mode. If that value is 0 we
|
/* CHECK_PROBLEMS_INTERVAL defines how often we check the existence of
|
||||||
* don't check at all. All values are in seconds. */
|
* homedir. Value is in seconds. */
|
||||||
# define TIMERTICK_INTERVAL (4)
|
#define CHECK_PROBLEMS_INTERVAL (4)
|
||||||
# define CHECK_OWN_SOCKET_INTERVAL (60)
|
|
||||||
|
|
||||||
/* The list of open file descriptors at startup. Note that this list
|
/* The list of open file descriptors at startup. Note that this list
|
||||||
* has been allocated using the standard malloc. */
|
* has been allocated using the standard malloc. */
|
||||||
@ -171,8 +170,10 @@ static int shutdown_pending;
|
|||||||
/* Flag indicating to start the daemon even if one already runs. */
|
/* Flag indicating to start the daemon even if one already runs. */
|
||||||
static int steal_socket;
|
static int steal_socket;
|
||||||
|
|
||||||
/* Counter for the currently running own socket checks. */
|
/* Flag to monitor problems. */
|
||||||
static int check_own_socket_running;
|
static int problem_detected;
|
||||||
|
#define KEYBOXD_PROBLEM_SOCKET_TAKEOVER (1 << 0)
|
||||||
|
#define KEYBOXD_PROBLEM_HOMEDIR_REMOVED (1 << 1)
|
||||||
|
|
||||||
/* Flag to indicate that we shall not watch our own socket. */
|
/* Flag to indicate that we shall not watch our own socket. */
|
||||||
static int disable_check_own_socket;
|
static int disable_check_own_socket;
|
||||||
@ -192,6 +193,17 @@ static assuan_sock_nonce_t socket_nonce;
|
|||||||
* Let's try this as default. Change at runtime with --listen-backlog. */
|
* Let's try this as default. Change at runtime with --listen-backlog. */
|
||||||
static int listen_backlog = 64;
|
static int listen_backlog = 64;
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
/* The event to break the select call. */
|
||||||
|
static HANDLE the_event2;
|
||||||
|
#elif defined(HAVE_PSELECT_NO_EINTR)
|
||||||
|
/* An FD to break the select call. */
|
||||||
|
static int event_pipe_fd;
|
||||||
|
#else
|
||||||
|
/* PID of the main thread. */
|
||||||
|
static pid_t main_thread_pid;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Name of a config file, which will be reread on a HUP if it is not NULL. */
|
/* Name of a config file, which will be reread on a HUP if it is not NULL. */
|
||||||
static char *config_filename;
|
static char *config_filename;
|
||||||
|
|
||||||
@ -199,11 +211,6 @@ static char *config_filename;
|
|||||||
* the log file after a SIGHUP if it didn't changed. Malloced. */
|
* the log file after a SIGHUP if it didn't changed. Malloced. */
|
||||||
static char *current_logfile;
|
static char *current_logfile;
|
||||||
|
|
||||||
/* This flag is true if the inotify mechanism for detecting the
|
|
||||||
* removal of the homedir is active. This flag is used to disable the
|
|
||||||
* alternative but portable stat based check. */
|
|
||||||
static int have_homedir_inotify;
|
|
||||||
|
|
||||||
/* Number of active connections. */
|
/* Number of active connections. */
|
||||||
static int active_connections;
|
static int active_connections;
|
||||||
|
|
||||||
@ -250,8 +257,11 @@ static void kbxd_init_default_ctrl (ctrl_t ctrl);
|
|||||||
static void kbxd_deinit_default_ctrl (ctrl_t ctrl);
|
static void kbxd_deinit_default_ctrl (ctrl_t ctrl);
|
||||||
|
|
||||||
static void handle_connections (gnupg_fd_t listen_fd);
|
static void handle_connections (gnupg_fd_t listen_fd);
|
||||||
static void check_own_socket (void);
|
|
||||||
static int check_for_running_kbxd (int silent);
|
static int check_for_running_kbxd (int silent);
|
||||||
|
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||||
|
static void *check_own_socket_thread (void *arg);
|
||||||
|
#endif
|
||||||
|
static void *check_others_thread (void *arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions.
|
* Functions.
|
||||||
@ -1055,6 +1065,44 @@ get_kbxd_active_connection_count (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Under W32, this function returns the handle of the scdaemon
|
||||||
|
notification event. Calling it the first time creates that
|
||||||
|
event. */
|
||||||
|
#if defined(HAVE_W32_SYSTEM)
|
||||||
|
static void *
|
||||||
|
create_an_event (void)
|
||||||
|
{
|
||||||
|
HANDLE h, h2;
|
||||||
|
SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
|
||||||
|
|
||||||
|
/* We need to use a manual reset event object due to the way our
|
||||||
|
w32-pth wait function works: If we would use an automatic
|
||||||
|
reset event we are not able to figure out which handle has
|
||||||
|
been signaled because at the time we single out the signaled
|
||||||
|
handles using WFSO the event has already been reset due to
|
||||||
|
the WFMO. */
|
||||||
|
h = CreateEvent (&sa, TRUE, FALSE, NULL);
|
||||||
|
if (!h)
|
||||||
|
log_error ("can't create an event: %s\n", w32_strerror (-1) );
|
||||||
|
else if (!DuplicateHandle (GetCurrentProcess(), h,
|
||||||
|
GetCurrentProcess(), &h2,
|
||||||
|
EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
|
||||||
|
{
|
||||||
|
log_error ("setting synchronize for an event failed: %s\n",
|
||||||
|
w32_strerror (-1) );
|
||||||
|
CloseHandle (h);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CloseHandle (h);
|
||||||
|
return h2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
/* Create a name for the socket in the home directory as using
|
/* Create a name for the socket in the home directory as using
|
||||||
* STANDARD_NAME. We also check for valid characters as well as
|
* STANDARD_NAME. We also check for valid characters as well as
|
||||||
* against a maximum allowed length for a Unix domain socket is done.
|
* against a maximum allowed length for a Unix domain socket is done.
|
||||||
@ -1267,38 +1315,6 @@ create_directories (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the worker for the ticker. It is called every few seconds
|
|
||||||
* and may only do fast operations. */
|
|
||||||
static void
|
|
||||||
handle_tick (void)
|
|
||||||
{
|
|
||||||
static time_t last_minute;
|
|
||||||
struct stat statbuf;
|
|
||||||
|
|
||||||
if (!last_minute)
|
|
||||||
last_minute = time (NULL);
|
|
||||||
|
|
||||||
/* Code to be run from time to time. */
|
|
||||||
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
|
||||||
if (last_minute + CHECK_OWN_SOCKET_INTERVAL <= time (NULL))
|
|
||||||
{
|
|
||||||
check_own_socket ();
|
|
||||||
last_minute = time (NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the homedir is still available. */
|
|
||||||
if (!shutdown_pending
|
|
||||||
&& !have_homedir_inotify
|
|
||||||
&& gnupg_stat (gnupg_homedir (), &statbuf) && errno == ENOENT)
|
|
||||||
{
|
|
||||||
shutdown_pending = 1;
|
|
||||||
log_info ("homedir has been removed - shutting down\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* A global function which allows us to call the reload stuff from
|
/* A global function which allows us to call the reload stuff from
|
||||||
* other places too. This is only used when build for W32. */
|
* other places too. This is only used when build for W32. */
|
||||||
void
|
void
|
||||||
@ -1344,6 +1360,11 @@ handle_signal (int signo)
|
|||||||
kbxd_sigusr2_action ();
|
kbxd_sigusr2_action ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SIGCONT:
|
||||||
|
/* Do nothing, but break the syscall. */
|
||||||
|
log_debug ("SIGCONT received - breaking select\n");
|
||||||
|
break;
|
||||||
|
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!shutdown_pending)
|
if (!shutdown_pending)
|
||||||
log_info ("SIGTERM received - shutting down ...\n");
|
log_info ("SIGTERM received - shutting down ...\n");
|
||||||
@ -1435,6 +1456,28 @@ start_connection_thread (void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboxd_kick_the_loop (void)
|
||||||
|
{
|
||||||
|
/* Kick the select loop. */
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
int ret = SetEvent (the_event2);
|
||||||
|
if (ret == 0)
|
||||||
|
log_error ("SetEvent for agent_kick_the_loop failed: %s\n",
|
||||||
|
w32_strerror (-1));
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
write (event_pipe_fd, "", 1);
|
||||||
|
# else
|
||||||
|
int ret = kill (main_thread_pid, SIGCONT);
|
||||||
|
if (ret < 0)
|
||||||
|
log_error ("sending signal for agent_kick_the_loop failed: %s\n",
|
||||||
|
gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Connection handler loop. Wait for connection requests and spawn a
|
/* Connection handler loop. Wait for connection requests and spawn a
|
||||||
* thread after accepting a connection. */
|
* thread after accepting a connection. */
|
||||||
static void
|
static void
|
||||||
@ -1449,12 +1492,14 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
gnupg_fd_t fd;
|
gnupg_fd_t fd;
|
||||||
int nfd;
|
int nfd;
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
struct timespec abstime;
|
|
||||||
struct timespec curtime;
|
|
||||||
struct timespec timeout;
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
HANDLE events[2];
|
HANDLE events[2];
|
||||||
unsigned int events_set;
|
unsigned int events_set;
|
||||||
|
#else
|
||||||
|
int signo;
|
||||||
|
# ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
int pipe_fd[2];
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
int sock_inotify_fd = -1;
|
int sock_inotify_fd = -1;
|
||||||
int home_inotify_fd = -1;
|
int home_inotify_fd = -1;
|
||||||
@ -1465,7 +1510,7 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
} listentbl[] = {
|
} listentbl[] = {
|
||||||
{ "std", start_connection_thread },
|
{ "std", start_connection_thread },
|
||||||
};
|
};
|
||||||
|
int have_homedir_inotify = 0;
|
||||||
|
|
||||||
ret = npth_attr_init(&tattr);
|
ret = npth_attr_init(&tattr);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1478,10 +1523,23 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
npth_sigev_add (SIGUSR1);
|
npth_sigev_add (SIGUSR1);
|
||||||
npth_sigev_add (SIGUSR2);
|
npth_sigev_add (SIGUSR2);
|
||||||
npth_sigev_add (SIGINT);
|
npth_sigev_add (SIGINT);
|
||||||
|
npth_sigev_add (SIGCONT);
|
||||||
npth_sigev_add (SIGTERM);
|
npth_sigev_add (SIGTERM);
|
||||||
npth_sigev_fini ();
|
npth_sigev_fini ();
|
||||||
|
# ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
ret = gnupg_create_pipe (pipe_fd);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event_pipe_fd = pipe_fd[1];
|
||||||
|
# else
|
||||||
|
main_thread_pid = getpid ();
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
events[0] = INVALID_HANDLE_VALUE;
|
events[0] = the_event2 = create_an_event ();
|
||||||
|
events[1] = INVALID_HANDLE_VALUE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (disable_check_own_socket)
|
if (disable_check_own_socket)
|
||||||
@ -1503,6 +1561,26 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
else
|
else
|
||||||
have_homedir_inotify = 1;
|
have_homedir_inotify = 1;
|
||||||
|
|
||||||
|
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||||
|
if (!disable_check_own_socket && sock_inotify_fd == -1)
|
||||||
|
{
|
||||||
|
npth_t thread;
|
||||||
|
|
||||||
|
err = npth_create (&thread, &tattr, check_own_socket_thread, NULL);
|
||||||
|
if (err)
|
||||||
|
log_error ("error spawning check_own_socket_thread: %s\n", strerror (err));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!have_homedir_inotify)
|
||||||
|
{
|
||||||
|
npth_t thread;
|
||||||
|
|
||||||
|
err = npth_create (&thread, &tattr, check_others_thread, NULL);
|
||||||
|
if (err)
|
||||||
|
log_error ("error spawning check_others_thread: %s\n", strerror (err));
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO (&fdset);
|
FD_ZERO (&fdset);
|
||||||
FD_SET (FD2INT (listen_fd), &fdset);
|
FD_SET (FD2INT (listen_fd), &fdset);
|
||||||
nfd = FD2NUM (listen_fd);
|
nfd = FD2NUM (listen_fd);
|
||||||
@ -1521,9 +1599,6 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
|
|
||||||
listentbl[0].l_fd = listen_fd;
|
listentbl[0].l_fd = listen_fd;
|
||||||
|
|
||||||
npth_clock_gettime (&abstime);
|
|
||||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* Shutdown test. */
|
/* Shutdown test. */
|
||||||
@ -1556,28 +1631,21 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
|
|
||||||
read_fdset = fdset;
|
read_fdset = fdset;
|
||||||
|
|
||||||
npth_clock_gettime (&curtime);
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
if (!(npth_timercmp (&curtime, &abstime, <)))
|
FD_SET (pipe_fd[0], &read_fdset);
|
||||||
{
|
if (nfd < pipe_fd[0])
|
||||||
/* Timeout. */
|
nfd = pipe_fd[0];
|
||||||
handle_tick ();
|
#endif
|
||||||
npth_clock_gettime (&abstime);
|
|
||||||
abstime.tv_sec += TIMERTICK_INTERVAL;
|
|
||||||
}
|
|
||||||
npth_timersub (&abstime, &curtime, &timeout);
|
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
|
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, NULL,
|
||||||
npth_sigev_sigmask ());
|
npth_sigev_sigmask ());
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
{
|
while (npth_sigev_get_pending (&signo))
|
||||||
int signo;
|
handle_signal (signo);
|
||||||
while (npth_sigev_get_pending (&signo))
|
|
||||||
handle_signal (signo);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout,
|
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, NULL,
|
||||||
events, &events_set);
|
events, &events_set);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
@ -1593,6 +1661,22 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
gnupg_sleep (1);
|
gnupg_sleep (1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((problem_detected & KEYBOXD_PROBLEM_SOCKET_TAKEOVER))
|
||||||
|
{
|
||||||
|
/* We may not remove the socket as it is now in use by another
|
||||||
|
server. */
|
||||||
|
inhibit_socket_removal = 1;
|
||||||
|
shutdown_pending = 2;
|
||||||
|
log_info ("this process is useless - shutting down\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((problem_detected & KEYBOXD_PROBLEM_HOMEDIR_REMOVED))
|
||||||
|
{
|
||||||
|
shutdown_pending = 1;
|
||||||
|
log_info ("homedir has been removed - shutting down\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
{
|
{
|
||||||
/* Interrupt or timeout. Will be handled when calculating the
|
/* Interrupt or timeout. Will be handled when calculating the
|
||||||
@ -1600,6 +1684,15 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
if (FD_ISSET (pipe_fd[0], &read_fdset))
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
read (pipe_fd[0], buf, sizeof buf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The inotify fds are set even when a shutdown is pending (see
|
/* The inotify fds are set even when a shutdown is pending (see
|
||||||
* above). So we must handle them in any case. To avoid that
|
* above). So we must handle them in any case. To avoid that
|
||||||
* they trigger a second time we close them immediately. */
|
* they trigger a second time we close them immediately. */
|
||||||
@ -1670,13 +1763,21 @@ handle_connections (gnupg_fd_t listen_fd)
|
|||||||
close (sock_inotify_fd);
|
close (sock_inotify_fd);
|
||||||
if (home_inotify_fd != -1)
|
if (home_inotify_fd != -1)
|
||||||
close (home_inotify_fd);
|
close (home_inotify_fd);
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
if (the_event2 != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (the_event2);
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
close (pipe_fd[0]);
|
||||||
|
close (pipe_fd[1]);
|
||||||
|
#endif
|
||||||
cleanup ();
|
cleanup ();
|
||||||
log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
|
log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
|
||||||
npth_attr_destroy (&tattr);
|
npth_attr_destroy (&tattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if CHECK_OWN_SOCKET_INTERVAL > 0
|
||||||
/* Helper for check_own_socket. */
|
/* Helper for check_own_socket. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
|
check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
|
||||||
@ -1687,20 +1788,18 @@ check_own_socket_pid_cb (void *opaque, const void *buffer, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The thread running the actual check. We need to run this in a
|
/* Check whether we are still listening on our own socket. In case
|
||||||
* separate thread so that check_own_thread can be called from the
|
another gpg-agent process started after us has taken ownership of
|
||||||
* timer tick. */
|
our socket, we would linger around without any real task. Thus we
|
||||||
static void *
|
better check once in a while whether we are really needed. */
|
||||||
check_own_socket_thread (void *arg)
|
static int
|
||||||
|
do_check_own_socket (const char *sockname)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char *sockname = arg;
|
|
||||||
assuan_context_t ctx = NULL;
|
assuan_context_t ctx = NULL;
|
||||||
membuf_t mb;
|
membuf_t mb;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
check_own_socket_running++;
|
|
||||||
|
|
||||||
rc = assuan_new (&ctx);
|
rc = assuan_new (&ctx);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
@ -1738,57 +1837,70 @@ check_own_socket_thread (void *arg)
|
|||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (sockname);
|
|
||||||
if (ctx)
|
if (ctx)
|
||||||
assuan_release (ctx);
|
assuan_release (ctx);
|
||||||
if (rc)
|
|
||||||
{
|
return rc;
|
||||||
/* We may not remove the socket as it is now in use by another
|
|
||||||
* server. */
|
|
||||||
inhibit_socket_removal = 1;
|
|
||||||
shutdown_pending = 2;
|
|
||||||
log_info ("this process is useless - shutting down\n");
|
|
||||||
}
|
|
||||||
check_own_socket_running--;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The thread running the actual check. */
|
||||||
/* Check whether we are still listening on our own socket. In case
|
static void *
|
||||||
* another keyboxd process started after us has taken ownership of our
|
check_own_socket_thread (void *arg)
|
||||||
* socket, we would linger around without any real task. Thus we
|
|
||||||
* better check once in a while whether we are really needed. */
|
|
||||||
static void
|
|
||||||
check_own_socket (void)
|
|
||||||
{
|
{
|
||||||
char *sockname;
|
char *sockname;
|
||||||
npth_t thread;
|
|
||||||
npth_attr_t tattr;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (disable_check_own_socket)
|
(void)arg;
|
||||||
return;
|
|
||||||
|
|
||||||
if (check_own_socket_running || shutdown_pending)
|
|
||||||
return; /* Still running or already shutting down. */
|
|
||||||
|
|
||||||
sockname = make_filename_try (gnupg_socketdir (), KEYBOXD_SOCK_NAME, NULL);
|
sockname = make_filename_try (gnupg_socketdir (), KEYBOXD_SOCK_NAME, NULL);
|
||||||
if (!sockname)
|
if (!sockname)
|
||||||
return; /* Out of memory. */
|
return NULL; /* Out of memory. */
|
||||||
|
|
||||||
err = npth_attr_init (&tattr);
|
while (!problem_detected)
|
||||||
if (err)
|
|
||||||
{
|
{
|
||||||
xfree (sockname);
|
if (shutdown_pending)
|
||||||
return;
|
goto leave;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
gnupg_sleep (CHECK_OWN_SOCKET_INTERVAL);
|
||||||
|
|
||||||
|
if (do_check_own_socket (sockname))
|
||||||
|
problem_detected |= KEYBOXD_PROBLEM_SOCKET_TAKEOVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboxd_kick_the_loop ();
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (sockname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The thread running other checks. */
|
||||||
|
static void *
|
||||||
|
check_others_thread (void *arg)
|
||||||
|
{
|
||||||
|
const char *homedir = gnupg_homedir ();
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
while (!problem_detected)
|
||||||
|
{
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
if (shutdown_pending)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
gnupg_sleep (CHECK_PROBLEMS_INTERVAL);
|
||||||
|
|
||||||
|
/* Check whether the homedir is still available. */
|
||||||
|
if (gnupg_stat (homedir, &statbuf) && errno == ENOENT)
|
||||||
|
problem_detected |= KEYBOXD_PROBLEM_HOMEDIR_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboxd_kick_the_loop ();
|
||||||
|
|
||||||
|
leave:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Figure out whether a keyboxd is available and running. Prints an
|
/* Figure out whether a keyboxd is available and running. Prints an
|
||||||
|
Loading…
x
Reference in New Issue
Block a user