]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
tail: use the inotify backend also with --pid=PID
authorGiuseppe Scrivano <gscrivano@gnu.org>
Sun, 26 Jul 2009 11:22:57 +0000 (13:22 +0200)
committerJim Meyering <meyering@redhat.com>
Tue, 28 Jul 2009 07:31:54 +0000 (09:31 +0200)
* src/tail.c (tail_forever_inotify): When a PID is specified, use
select to block for no more than sleep_interval seconds at a time,
and check for process death upon timeout.
(main): Adapt to new tail_forever_inotify interface.

src/tail.c

index fd44e220def4d4bba729557b07451d6645a40dc9..a73ffa25df6369c72a66b62edd9e1f83df25c746 100644 (file)
@@ -50,6 +50,8 @@
 #if HAVE_INOTIFY
 # include "hash.h"
 # include <sys/inotify.h>
+/* `select' is used by tail_forever_inotify.  */
+# include <sys/select.h>
 #endif
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -1162,7 +1164,8 @@ wd_comparator (const void *e1, const void *e2)
    Check modifications using the inotify events system.  */
 
 static void
-tail_forever_inotify (int wd, struct File_spec *f, size_t n_files)
+tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
+                      double sleep_interval)
 {
   size_t i;
   unsigned int max_realloc = 3;
@@ -1253,6 +1256,36 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files)
 
       struct inotify_event *ev;
 
+      /* When watching a PID, ensure that a read from WD will not block
+         indefinetely.  */
+      if (pid)
+        {
+          fd_set rfd;
+          struct timeval select_timeout;
+          int n_descriptors;
+
+          FD_ZERO (&rfd);
+          FD_SET (wd, &rfd);
+
+          select_timeout.tv_sec = (time_t) sleep_interval;
+          select_timeout.tv_usec = 1000000000 * (sleep_interval
+                                                 - select_timeout.tv_sec);
+
+          n_descriptors = select (wd + 1, &rfd, NULL, NULL, &select_timeout);
+
+          if (n_descriptors == -1)
+            error (EXIT_FAILURE, errno, _("error monitoring inotify event"));
+
+          if (n_descriptors == 0)
+            {
+              /* See if the process we are monitoring is still alive.  */
+              if (kill (pid, 0) != 0 && errno != EPERM)
+                break;
+
+              continue;
+            }
+        }
+
       if (len <= evbuf_off)
         {
           len = safe_read (wd, evbuf, evlen);
@@ -1940,18 +1973,15 @@ main (int argc, char **argv)
   if (forever)
     {
 #if HAVE_INOTIFY
-      if (pid == 0)
+      int wd = inotify_init ();
+      if (wd < 0)
+        error (0, errno, _("inotify cannot be used, reverting to polling"));
+      else
         {
-          int wd = inotify_init ();
-          if (wd < 0)
-            error (0, errno, _("inotify cannot be used, reverting to polling"));
-          else
-            {
-              tail_forever_inotify (wd, F, n_files);
+          tail_forever_inotify (wd, F, n_files, sleep_interval);
 
-              /* The only way the above returns is upon failure.  */
-              exit (EXIT_FAILURE);
-            }
+          /* The only way the above returns is upon failure.  */
+          exit (EXIT_FAILURE);
         }
 #endif
       tail_forever (F, n_files, sleep_interval);