agent,dirmngr: Check for homedir removal also using stat(2).
authorWerner Koch <wk@gnupg.org>
Wed, 26 Jul 2017 08:02:52 +0000 (10:02 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 26 Jul 2017 08:27:36 +0000 (10:27 +0200)
* 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>
agent/gpg-agent.c
dirmngr/dirmngr.c

index 2906cc3..e4fdf2e 100644 (file)
@@ -380,10 +380,20 @@ static const char *debug_level;
 static char *current_logfile;
 
 /* 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
  watched. */
+ * running.  We record the PID of the parent here or -1 if it should
* be watched.  */
 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.  */
 static int active_connections;
 
@@ -1704,6 +1714,12 @@ main (int argc, char **argv )
           log_get_prefix (&oldflags);
           log_set_prefix (NULL, oldflags | GPGRT_LOG_RUN_DETACHED);
           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)
 {
   static time_t last_minute;
+  struct stat statbuf;
 
   if (!last_minute)
     last_minute = time (NULL);
@@ -2329,6 +2346,14 @@ handle_tick (void)
     }
 #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 ())))
     {
       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));
     }
+  else
+    have_homedir_inotify = 1;
 
   /* 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
index 5f3a4cd..1ddc568 100644 (file)
@@ -334,8 +334,9 @@ static int network_activity_seen;
 static strlist_t hkp_cacert_filenames;
 
 
-/* The timer tick used for housekeeping stuff.  */
-#define TIMERTICK_INTERVAL         (60)
+/* The timer tick used for housekeeping stuff.  The second constant is used when a shutdown is pending.  */
+#define TIMERTICK_INTERVAL           (60)
+#define TIMERTICK_INTERVAL_SHUTDOWN  (4)
 
 /* How oft to run the housekeeping.  */
 #define HOUSEKEEPING_INTERVAL      (600)
@@ -1967,6 +1968,8 @@ time_for_housekeeping_p (time_t curtime)
 static void
 handle_tick (void)
 {
+  struct stat statbuf;
+
   if (time_for_housekeeping_p (gnupg_get_time ()))
     {
       npth_t thread;
@@ -1986,6 +1989,14 @@ handle_tick (void)
           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);
       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 ();
          npth_clock_gettime (&abstime);
-         abstime.tv_sec += TIMERTICK_INTERVAL;
+         abstime.tv_sec += (shutdown_pending
+                             ? TIMERTICK_INTERVAL_SHUTDOWN
+                             : TIMERTICK_INTERVAL);
        }
       npth_timersub (&abstime, &curtime, &timeout);