X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=fb621cdef69fd39b243a27f02a4276a3eb4b3e8c;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=0bbe4a87609c836239b693642957276d33f64a89;hpb=07faf451b99879183ed7e909e43a0e065be1ee7f;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 0bbe4a87..fb621cde 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,5 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991-2006 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2008 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 @@ -93,7 +93,7 @@ no_malloc_number_to_string (long num) num = -num; } - while ((num > 0) && (num_digits < sizeof(string - 1))) + while ((num > 0) && (num_digits < sizeof(string) - 1)) { int digit; digit = (int) num % 10; @@ -360,12 +360,20 @@ static int block_sigchld_handler = 0; block_sigchld (void) { #ifdef HAVE_SIGACTION + struct sigaction sa; sigset_t child_set; + + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); + sigemptyset (&child_set); sigaddset (&child_set, SIGCHLD); - sigaddset (&child_set, SIGPIPE); sigprocmask (SIG_BLOCK, &child_set, 0); -#endif /* HAVE_SIGACTION */ + +#else /* !HAVE_SIGACTION */ + signal (SIGPIPE, SIG_IGN); +#endif /* !HAVE_SIGACTION */ block_sigchld_handler++; @@ -380,12 +388,20 @@ void unblock_sigchld (void) { #ifdef HAVE_SIGACTION + struct sigaction sa; sigset_t child_set; + + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_DFL; + sigaction(SIGPIPE, &sa, NULL); + sigemptyset(&child_set); sigaddset(&child_set, SIGCHLD); - sigaddset(&child_set, SIGPIPE); sigprocmask(SIG_UNBLOCK, &child_set, 0); -#endif /* HAVE_SIGACTION */ + +#else /* !HAVE_SIGACTION */ + signal(SIGPIPE, SIG_DFL); +#endif /* !HAVE_SIGACTION */ block_sigchld_handler--; } @@ -835,7 +851,7 @@ fork_and_exec (saver_screen_info *ssi, const char *command) case 0: close (ConnectionNumber (si->dpy)); /* close display fd */ limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); - hack_subproc_environment (ssi); /* set $DISPLAY */ + hack_subproc_environment (ssi->screen, ssi->screensaver_window); if (p->verbose_p) fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n", @@ -862,14 +878,22 @@ fork_and_exec (saver_screen_info *ssi, const char *command) } -static void -spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) +void +spawn_screenhack (saver_screen_info *ssi) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; - raise_window (si, first_time_p, True, False); XFlush (si->dpy); + if (!monitor_powered_on_p (si)) + { + if (si->prefs.verbose_p) + fprintf (stderr, + "%s: %d: X says monitor has powered down; " + "not launching a hack.\n", blurb(), ssi->number); + return; + } + if (p->screenhacks_count) { screenhack *hack; @@ -1001,55 +1025,28 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) break; } } -} - -void -spawn_screenhack (saver_info *si, Bool first_time_p) -{ - if (monitor_powered_on_p (si)) - { - int i; - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - spawn_screenhack_1 (ssi, first_time_p); - } - } - else if (si->prefs.verbose_p) - fprintf (stderr, - "%s: X says monitor has powered down; " - "not launching a hack.\n", blurb()); - - store_saver_status (si); /* store current hack numbers */ + store_saver_status (si); /* store current hack number */ } void -kill_screenhack (saver_info *si) +kill_screenhack (saver_screen_info *ssi) { - int i; - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - if (ssi->pid) - kill_job (si, ssi->pid, SIGTERM); - ssi->pid = 0; - } + saver_info *si = ssi->global; + if (ssi->pid) + kill_job (si, ssi->pid, SIGTERM); + ssi->pid = 0; } void -suspend_screenhack (saver_info *si, Bool suspend_p) +suspend_screenhack (saver_screen_info *ssi, Bool suspend_p) { #ifdef SIGSTOP /* older VMS doesn't have it... */ - int i; - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - if (ssi->pid) - kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT)); - } + saver_info *si = ssi->global; + if (ssi->pid) + kill_job (si, ssi->pid, (suspend_p ? SIGSTOP : SIGCONT)); #endif /* SIGSTOP */ } @@ -1121,7 +1118,7 @@ hack_environment (saver_info *si) void -hack_subproc_environment (saver_screen_info *ssi) +hack_subproc_environment (Screen *screen, Window saver_window) { /* Store $DISPLAY into the environment, so that the $DISPLAY variable that the spawned processes inherit is correct. First, it must be on the same @@ -1136,8 +1133,8 @@ hack_subproc_environment (saver_screen_info *ssi) us to (eventually) run multiple hacks in Xinerama mode, where each hack has the same $DISPLAY but a different piece of glass. */ - saver_info *si = ssi->global; - const char *odpy = DisplayString (si->dpy); + Display *dpy = DisplayOfScreen (screen); + const char *odpy = DisplayString (dpy); char *ndpy = (char *) malloc (strlen(odpy) + 20); char *nssw = (char *) malloc (40); char *s, *c; @@ -1154,10 +1151,9 @@ hack_subproc_environment (saver_screen_info *ssi) while (isdigit(*s)) s++; /* skip over dpy number */ while (*s == '.') s++; /* skip over dot */ if (s[-1] != '.') *s++ = '.'; /* put on a dot */ - sprintf(s, "%d", ssi->real_screen_number); /* put on screen number */ + sprintf(s, "%d", screen_number (screen)); /* put on screen number */ - sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", - (unsigned long) ssi->screensaver_window); + sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", (unsigned long) saver_window); /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems any more, right? It's not Posix, but everyone seems to have it. */ @@ -1178,12 +1174,13 @@ hack_subproc_environment (saver_screen_info *ssi) /* GL crap */ Visual * -get_best_gl_visual (saver_screen_info *ssi) +get_best_gl_visual (saver_info *si, Screen *screen) { - saver_info *si = ssi->global; pid_t forked; int fds [2]; int in, out; + int errfds[2]; + int errin = -1, errout = -1; char buf[1024]; char *av[10]; @@ -1201,6 +1198,23 @@ get_best_gl_visual (saver_screen_info *ssi) 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. + */ + switch ((int) (forked = fork ())) { case -1: @@ -1211,23 +1225,32 @@ get_best_gl_visual (saver_screen_info *ssi) } 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; } - hack_subproc_environment (ssi); /* set $DISPLAY */ + + 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. */ - if (errno != ENOENT || si->prefs.verbose_p) + if (errno != ENOENT /* || si->prefs.verbose_p */ ) { - /* Ignore "no such file or directory" errors, unless verbose. + /* Ignore "no such file or directory" errors. Issue all other exec errors, though. */ sprintf (buf, "%s: running %s", blurb(), av[0]); perror (buf); @@ -1251,9 +1274,17 @@ get_best_gl_visual (saver_screen_info *ssi) *buf = 0; fclose (f); + if (! si->prefs.verbose_p) + { + close (errout); + close (errin); + } + /* Wait for the child to die. */ waitpid (-1, &wait_status, 0); + unblock_sigchld(); /* child is dead and waited, unblock now. */ + if (1 == sscanf (buf, "0x%lx %c", &v, &c)) result = (int) v; @@ -1275,12 +1306,13 @@ get_best_gl_visual (saver_screen_info *ssi) } else { - Visual *v = id_to_visual (ssi->screen, result); + Visual *v = id_to_visual (screen, result); if (si->prefs.verbose_p) fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n", - blurb(), ssi->number, + blurb(), screen_number (screen), av[0], result, - (v == ssi->default_visual ? " (default)" : "")); + (v == DefaultVisualOfScreen (screen) + ? " (default)" : "")); return v; } }