From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / driver / subprocs.c
index ecbaeb24a31080ca669cdd698581c6ad0aa7d860..4f327e95851bcfa72f8989b2f055ddd32e1de0e0 100644 (file)
@@ -1,5 +1,5 @@
 /* subprocs.c --- choosing, spawning, and killing screenhacks.
- * xscreensaver, Copyright (c) 1991-2015 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2017 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -44,6 +44,7 @@
 #endif /* VMS */
 
 #include <signal.h>            /* for the signal names */
+#include <time.h>
 
 #if !defined(SIGCHLD) && defined(SIGCLD)
 # define SIGCHLD SIGCLD
@@ -213,6 +214,7 @@ struct screenhack_job {
   pid_t pid;
   int screen;
   enum job_status status;
+  time_t launched, killed;
   struct screenhack_job *next;
 };
 
@@ -228,14 +230,21 @@ show_job_list (void)
   struct screenhack_job *job;
   fprintf(stderr, "%s: job list:\n", blurb());
   for (job = jobs; job; job = job->next)
-    fprintf (stderr, "  %5ld: %2d: (%s) %s\n",
-            (long) job->pid,
-             job->screen,
-            (job->status == job_running ? "running" :
-             job->status == job_stopped ? "stopped" :
-             job->status == job_killed  ? " killed" :
-             job->status == job_dead    ? "   dead" : "    ???"),
-            job->name);
+    {
+      char b[] = "           ??:??:??     ";
+      char *t = (job->killed   ? timestring (job->killed) :
+                 job->launched ? timestring (job->launched) : b);
+      t += 11;
+      t[8] = 0;
+        fprintf (stderr, "  %5ld: %2d: (%s) %s %s\n",
+                 (long) job->pid,
+                 job->screen,
+                 (job->status == job_running ? "running" :
+                  job->status == job_stopped ? "stopped" :
+                  job->status == job_killed  ? " killed" :
+                  job->status == job_dead    ? "   dead" : "    ???"),
+                 t, job->name);
+    }
   fprintf (stderr, "\n");
 }
 
@@ -251,7 +260,6 @@ make_job (pid_t pid, int screen, const char *cmd)
   const char *in = cmd;
   char *out = name;
   int got_eq = 0;
-  int first = 1;
 
   clean_job_list();
 
@@ -266,7 +274,6 @@ make_job (pid_t pid, int screen, const char *cmd)
     {                                  /* then get the next token instead. */
       got_eq = 0;
       out = name;
-      first = 0;
       goto AGAIN;
     }
 
@@ -277,6 +284,8 @@ make_job (pid_t pid, int screen, const char *cmd)
   job->pid = pid;
   job->screen = screen;
   job->status = job_running;
+  job->launched = time ((time_t *) 0);
+  job->killed = 0;
   job->next = jobs;
   jobs = job;
 
@@ -315,6 +324,10 @@ static void
 clean_job_list (void)
 {
   struct screenhack_job *job, *prev, *next;
+  time_t now = time ((time_t *) 0);
+  static time_t last_warn = 0;
+  Bool warnedp = False;
+
   for (prev = 0, job = jobs, next = (job ? job->next : 0);
        job;
        prev = job, job = next, next = (job ? job->next : 0))
@@ -326,7 +339,21 @@ clean_job_list (void)
          free_job (job);
          job = prev;
        }
+      else if (job->status == job_killed &&
+               now - job->killed > 10 &&
+               now - last_warn   > 10)
+        {
+          fprintf (stderr,
+                   "%s: WARNING: pid %ld (%s) sent SIGTERM %ld seconds ago"
+                   " and did not die!\n",
+                   blurb(),
+                   (long) job->pid,
+                   job->name,
+                   (long) (now - job->killed));
+          warnedp = True;
+        }
     }
+  if (warnedp) last_warn = now;
 }
 
 
@@ -439,7 +466,10 @@ kill_job (saver_info *si, pid_t pid, int signal)
     }
 
   switch (signal) {
-  case SIGTERM: job->status = job_killed;  break;
+  case SIGTERM:
+    job->status = job_killed;
+    job->killed = time ((time_t *) 0);
+    break;
 #ifdef SIGSTOP
     /* #### there must be a way to do this on VMS... */
   case SIGSTOP: job->status = job_stopped; break;
@@ -1272,6 +1302,7 @@ get_best_gl_visual (saver_info *si, Screen *screen)
       {
         int result = 0;
         int wait_status = 0;
+        pid_t pid = -1;
 
         FILE *f = fdopen (in, "r");
         unsigned long v = 0;
@@ -1290,8 +1321,17 @@ get_best_gl_visual (saver_info *si, Screen *screen)
             close (errin);
           }
 
-        /* Wait for the child to die. */
-        waitpid (-1, &wait_status, 0);
+        /* Wait for the child to die - wait for this pid only, not others. */
+        pid = waitpid (forked, &wait_status, 0);
+        if (si->prefs.debug_p)
+          {
+            write_string (STDERR_FILENO, blurb());
+            write_string (STDERR_FILENO, ": waitpid(");
+            write_long   (STDERR_FILENO, (long) forked);
+            write_string (STDERR_FILENO, ") ==> ");
+            write_long   (STDERR_FILENO, (long) pid);
+            write_string (STDERR_FILENO, "\n");
+          }
 
         unblock_sigchld();   /* child is dead and waited, unblock now. */