X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=29ad60092daf40880afdae6d1acb064b122ec48f;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=405a382b8bb6e70c94bd0de2aaee76e009bc1033;hpb=de460e831dc8578acfa8b72251ab9346c99c1f96;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 405a382b..29ad6009 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,5 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -213,6 +213,7 @@ struct screenhack_job { pid_t pid; int screen; enum job_status status; + time_t launched, killed; struct screenhack_job *next; }; @@ -228,14 +229,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"); } @@ -277,6 +285,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 +325,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 +340,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; } @@ -387,6 +415,11 @@ block_sigchld (void) void unblock_sigchld (void) { + if (block_sigchld_handler <= 0) + abort(); + + if (block_sigchld_handler <= 1) /* only unblock if count going to 0 */ + { #ifdef HAVE_SIGACTION struct sigaction sa; sigset_t child_set; @@ -402,6 +435,7 @@ unblock_sigchld (void) #else /* !HAVE_SIGACTION */ signal(SIGPIPE, SIG_DFL); #endif /* !HAVE_SIGACTION */ + } block_sigchld_handler--; } @@ -415,7 +449,7 @@ kill_job (saver_info *si, pid_t pid, int signal) clean_job_list(); - if (block_sigchld_handler) + if (in_signal_handler_p) /* This function should not be called from the signal handler. */ abort(); @@ -433,7 +467,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; @@ -484,6 +521,7 @@ static RETSIGTYPE sigchld_handler (int sig) { saver_info *si = global_si_kludge; /* I hate C so much... */ + in_signal_handler_p++; if (si->prefs.debug_p) { @@ -510,6 +548,7 @@ sigchld_handler (int sig) } init_sigchld(); + in_signal_handler_p--; } #endif /* SIGCHLD */ @@ -1099,7 +1138,9 @@ hack_environment (saver_info *si) if (def_path && *def_path) { const char *opath = getenv("PATH"); - char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); + char *npath; + if (! opath) opath = "/bin:/usr/bin"; /* WTF */ + npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); strcpy (npath, "PATH="); strcat (npath, def_path); strcat (npath, ":"); @@ -1179,6 +1220,8 @@ get_best_gl_visual (saver_info *si, Screen *screen) pid_t forked; int fds [2]; int in, out; + int errfds[2]; + int errin = -1, errout = -1; char buf[1024]; char *av[10]; @@ -1196,6 +1239,18 @@ get_best_gl_visual (saver_info *si, Screen *screen) in = fds [0]; out = fds [1]; + if (!si->prefs.verbose_p) + { + if (pipe (errfds)) + { + perror ("error creating pipe:"); + return 0; + } + + errin = errfds [0]; + errout = errfds [1]; + } + block_sigchld(); /* This blocks it in the parent and child, to avoid racing. It is never unblocked in the child before the child exits, but that doesn't matter. @@ -1211,16 +1266,25 @@ get_best_gl_visual (saver_info *si, Screen *screen) } case 0: { - int stdout_fd = 1; - close (in); /* don't need this one */ close (ConnectionNumber (si->dpy)); /* close display fd */ - if (dup2 (out, stdout_fd) < 0) /* pipe stdout */ + if (dup2 (out, STDOUT_FILENO) < 0) /* pipe stdout */ { perror ("could not dup() a new stdout:"); return 0; } + + if (! si->prefs.verbose_p) + { + close(errin); + if (dup2 (errout, STDERR_FILENO) < 0) + { + perror ("could not dup() a new stderr:"); + return 0; + } + } + hack_subproc_environment (screen, 0); /* set $DISPLAY */ execvp (av[0], av); /* shouldn't return. */ @@ -1251,6 +1315,12 @@ get_best_gl_visual (saver_info *si, Screen *screen) *buf = 0; fclose (f); + if (! si->prefs.verbose_p) + { + close (errout); + close (errin); + } + /* Wait for the child to die. */ waitpid (-1, &wait_status, 0);