agent,dirmngr: Check for homedir removal also using stat(2).

* agent/gpg-agent.c (have_homedir_inotify): New var.
(reliable_homedir_inotify): New var.
(main):  Set reliable_homedir_inotify.
(handle_tick): Call stat on the homedir.
(handle_connections): Mark availibility of the inotify watch.
* dirmngr/dirmngr.c (handle_tick): Call stat on the homedir.
(TIMERTICK_INTERVAL_SHUTDOWN): New.
(handle_connections): Depend tick interval on the shutdown state.
--

The stat call is used on systems which do not support inotify and also
when we assume that the inotify does not work reliable.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-07-26 10:02:52 +02:00
parent f4ec7697a9
commit d50c2eff8d
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 48 additions and 7 deletions

View File

@ -380,10 +380,20 @@ static const char *debug_level;
static char *current_logfile; static char *current_logfile;
/* The handle_tick() function may test whether a parent is still /* The handle_tick() function may test whether a parent is still
running. We record the PID of the parent here or -1 if it should be * running. We record the PID of the parent here or -1 if it should
watched. */ * be watched. */
static pid_t parent_pid = (pid_t)(-1); static pid_t parent_pid = (pid_t)(-1);
/* 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;
/* Depending on how gpg-agent was started, the homedir inotify watch
* may not be reliable. This flag is set if we assume that inotify
* works reliable. */
static int reliable_homedir_inotify;
/* Number of active connections. */ /* Number of active connections. */
static int active_connections; static int active_connections;
@ -1704,6 +1714,12 @@ main (int argc, char **argv )
log_get_prefix (&oldflags); log_get_prefix (&oldflags);
log_set_prefix (NULL, oldflags | GPGRT_LOG_RUN_DETACHED); log_set_prefix (NULL, oldflags | GPGRT_LOG_RUN_DETACHED);
opt.running_detached = 1; opt.running_detached = 1;
/* Unless we are running with a program given on the command
* line we can assume that the inotify things works and thus
* we can avoid tye regular stat calls. */
if (!argc)
reliable_homedir_inotify = 1;
} }
{ {
@ -2297,6 +2313,7 @@ static void
handle_tick (void) handle_tick (void)
{ {
static time_t last_minute; static time_t last_minute;
struct stat statbuf;
if (!last_minute) if (!last_minute)
last_minute = time (NULL); last_minute = time (NULL);
@ -2329,6 +2346,14 @@ handle_tick (void)
} }
#endif #endif
/* Check whether the homedir is still available. */
if (!shutdown_pending
&& (!have_homedir_inotify || !reliable_homedir_inotify)
&& stat (gnupg_homedir (), &statbuf) && errno == ENOENT)
{
shutdown_pending = 1;
log_info ("homedir has been removed - shutting down\n");
}
} }
@ -2803,9 +2828,11 @@ handle_connections (gnupg_fd_t listen_fd,
gnupg_homedir ()))) gnupg_homedir ())))
{ {
if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
log_info ("error enabling daemon termination bu homedir removal: %s\n", log_info ("error enabling daemon termination by homedir removal: %s\n",
gpg_strerror (err)); gpg_strerror (err));
} }
else
have_homedir_inotify = 1;
/* On Windows we need to fire up a separate thread to listen for /* On Windows we need to fire up a separate thread to listen for
requests from Putty (an SSH client), so we can replace Putty's requests from Putty (an SSH client), so we can replace Putty's

View File

@ -334,8 +334,9 @@ static int network_activity_seen;
static strlist_t hkp_cacert_filenames; static strlist_t hkp_cacert_filenames;
/* The timer tick used for housekeeping stuff. */ /* The timer tick used for housekeeping stuff. The second constant is used when a shutdown is pending. */
#define TIMERTICK_INTERVAL (60) #define TIMERTICK_INTERVAL (60)
#define TIMERTICK_INTERVAL_SHUTDOWN (4)
/* How oft to run the housekeeping. */ /* How oft to run the housekeeping. */
#define HOUSEKEEPING_INTERVAL (600) #define HOUSEKEEPING_INTERVAL (600)
@ -1967,6 +1968,8 @@ time_for_housekeeping_p (time_t curtime)
static void static void
handle_tick (void) handle_tick (void)
{ {
struct stat statbuf;
if (time_for_housekeeping_p (gnupg_get_time ())) if (time_for_housekeeping_p (gnupg_get_time ()))
{ {
npth_t thread; npth_t thread;
@ -1986,6 +1989,14 @@ handle_tick (void)
npth_attr_destroy (&tattr); npth_attr_destroy (&tattr);
} }
} }
/* Check whether the homedir is still available. */
if (!shutdown_pending
&& stat (gnupg_homedir (), &statbuf) && errno == ENOENT)
{
shutdown_pending = 1;
log_info ("homedir has been removed - shutting down\n");
}
} }
@ -2179,10 +2190,13 @@ handle_connections (assuan_fd_t listen_fd)
npth_clock_gettime (&curtime); npth_clock_gettime (&curtime);
if (!(npth_timercmp (&curtime, &abstime, <))) if (!(npth_timercmp (&curtime, &abstime, <)))
{ {
/* Timeout. */ /* Timeout. When a shutdown is pending we use a shorter
* interval to handle the shutdown more quickly. */
handle_tick (); handle_tick ();
npth_clock_gettime (&abstime); npth_clock_gettime (&abstime);
abstime.tv_sec += TIMERTICK_INTERVAL; abstime.tv_sec += (shutdown_pending
? TIMERTICK_INTERVAL_SHUTDOWN
: TIMERTICK_INTERVAL);
} }
npth_timersub (&abstime, &curtime, &timeout); npth_timersub (&abstime, &curtime, &timeout);