X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=4f327e95851bcfa72f8989b2f055ddd32e1de0e0;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hp=ffabe483f3b2936697e7262dc3749156c39a3ea8;hpb=3f438031d610c7e15fd33876a879b97e290e05fb;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index ffabe483..4f327e95 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,5 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991-2005 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2017 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 @@ -25,6 +25,7 @@ #endif #include /* sys/resource.h needs this for timeval */ +#include /* for PATH_MAX */ #ifdef HAVE_SYS_WAIT_H # include /* for waitpid() and associated macros */ @@ -43,6 +44,7 @@ #endif /* VMS */ #include /* for the signal names */ +#include #if !defined(SIGCHLD) && defined(SIGCLD) # define SIGCHLD SIGCLD @@ -65,12 +67,66 @@ extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ #define Widget void* #include "xscreensaver.h" +#include "exec.h" #include "yarandom.h" #include "visual.h" /* for id_to_visual() */ extern saver_info *global_si_kludge; /* I hate C so much... */ +/* Used when printing error/debugging messages from signal handlers. + */ +static const char * +no_malloc_number_to_string (long num) +{ + static char string[128] = ""; + int num_digits; + Bool negative_p = False; + + num_digits = 0; + + if (num == 0) + return "0"; + + if (num < 0) + { + negative_p = True; + num = -num; + } + + while ((num > 0) && (num_digits < sizeof(string) - 1)) + { + int digit; + digit = (int) num % 10; + num_digits++; + string[sizeof(string) - 1 - num_digits] = digit + '0'; + num /= 10; + } + + if (negative_p) + { + num_digits++; + string[sizeof(string) - 1 - num_digits] = '-'; + } + + return string + sizeof(string) - 1 - num_digits; +} + +/* Like write(), but runs strlen() on the arg to get the length. */ +static int +write_string (int fd, const char *str) +{ + return write (fd, str, strlen (str)); +} + +static int +write_long (int fd, long n) +{ + const char *str = no_malloc_number_to_string (n); + return write_string (fd, str); +} + + /* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size of a process's address space, i.e., the maximal brk(2) and mmap(2) values. Setting this lets you put a cap on how much memory a process can allocate. @@ -158,26 +214,37 @@ struct screenhack_job { pid_t pid; int screen; enum job_status status; + time_t launched, killed; struct screenhack_job *next; }; static struct screenhack_job *jobs = 0; -/* for debugging -- nothing calls this, but it's useful to invoke from gdb. */ +/* for debugging -- nothing calls this, but it's useful to invoke from gdb. + */ +void show_job_list (void); + void 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"); } @@ -193,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(); @@ -208,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; } @@ -219,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; @@ -257,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)) @@ -268,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; } @@ -302,12 +387,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++; @@ -321,13 +414,27 @@ 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; + + 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--; } @@ -341,7 +448,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(); @@ -359,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; @@ -410,10 +520,22 @@ 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) - fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(), + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(), (block_sigchld_handler ? " (blocked)" : "")); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": got SIGCHLD"); + + if (block_sigchld_handler) + write_string (STDERR_FILENO, " (blocked)\n"); + else + write_string (STDERR_FILENO, "\n"); + } if (block_sigchld_handler < 0) abort(); @@ -425,11 +547,13 @@ sigchld_handler (int sig) } init_sigchld(); + in_signal_handler_p--; } #endif /* SIGCHLD */ #ifndef VMS + static void await_dying_children (saver_info *si) { @@ -444,11 +568,29 @@ await_dying_children (saver_info *si) if (si->prefs.debug_p) { if (kid < 0 && errno) - fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(), - (long) kid, errno); - else - fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(), - (long) kid); + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(), + (long) kid, errno); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": waitpid(-1) ==> "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_long (STDERR_FILENO, (long) errno); + write_string (STDERR_FILENO, ")\n"); + } + else + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(), + (long) kid); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": waitpid(-1) ==> "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, "\n"); + } } /* 0 means no more children to reap. @@ -488,12 +630,38 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) if (!job || (exit_status != 0 && (p->verbose_p || job->status != job_killed))) - fprintf (stderr, - "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n", - blurb(), screen_no, (unsigned long) kid, name, exit_status); + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, + "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n", + blurb(), screen_no, (unsigned long) kid, name, exit_status); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") exited abnormally (code "); + write_long (STDERR_FILENO, (long) exit_status); + write_string (STDERR_FILENO, ").\n"); + } else if (p->verbose_p) - fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n", - blurb(), screen_no, (unsigned long) kid, name); + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n", + blurb(), screen_no, (unsigned long) kid, name); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") exited normally.\n"); + } if (job) job->status = job_dead; @@ -504,9 +672,23 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) !job || job->status != job_killed || WTERMSIG (wait_status) != SIGTERM) - fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n", - blurb(), screen_no, (unsigned long) kid, name, - signal_name (WTERMSIG(wait_status))); + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n", + blurb(), screen_no, (unsigned long) kid, name, + signal_name (WTERMSIG(wait_status))); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") terminated with signal "); + write_long (STDERR_FILENO, WTERMSIG(wait_status)); + write_string (STDERR_FILENO, ".\n"); + } if (job) job->status = job_dead; @@ -514,17 +696,41 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) else if (WIFSTOPPED (wait_status)) { if (p->verbose_p) - fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n", - blurb(), (unsigned long) kid, name, - signal_name (WSTOPSIG (wait_status))); + { + /* Don't call fprintf() from signal handlers, as it might malloc. + fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n", + blurb(), (unsigned long) kid, name, + signal_name (WSTOPSIG (wait_status))); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") stopped with signal "); + write_long (STDERR_FILENO, WSTOPSIG(wait_status)); + write_string (STDERR_FILENO, ".\n"); + } if (job) job->status = job_stopped; } else { + /* Don't call fprintf() from signal handlers, as it might malloc. fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!", blurb(), (unsigned long) kid, name); + */ + write_string (STDERR_FILENO, blurb()); + write_string (STDERR_FILENO, ": "); + write_long (STDERR_FILENO, (long) screen_no); + write_string (STDERR_FILENO, ": child pid "); + write_long (STDERR_FILENO, (long) kid); + write_string (STDERR_FILENO, " ("); + write_string (STDERR_FILENO, name); + write_string (STDERR_FILENO, ") died in a mysterious way!"); if (job) job->status = job_dead; } @@ -637,7 +843,8 @@ print_path_error (const char *program) fprintf (stderr, "\n"); *path = 0; # if defined(HAVE_GETCWD) - getcwd (path, sizeof(path)); + if (! getcwd (path, sizeof(path))) + *path = 0; # elif defined(HAVE_GETWD) getwd (path); # endif @@ -682,7 +889,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", @@ -709,14 +916,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; @@ -806,6 +1021,7 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) if (!force && (!hack->enabled_p || + !on_path_p (hack->command) || !select_visual_of_hack (ssi, hack))) { if (++retry_count > (p->screenhacks_count*4)) @@ -847,55 +1063,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 */ } @@ -948,7 +1137,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, ":"); @@ -967,7 +1158,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 @@ -982,25 +1173,27 @@ 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; + char *s, *c; strcpy (ndpy, "DISPLAY="); s = ndpy + strlen(ndpy); strcpy (s, odpy); - while (*s && *s != ':') s++; /* skip to colon */ - while (*s == ':') s++; /* skip over colons */ + /* We have to find the last colon since it is the boundary between + hostname & screen - IPv6 numeric format addresses may have many + colons before that point, and DECnet addresses always have two colons */ + c = strrchr(s,':'); /* skip to last colon */ + if (c != NULL) s = c+1; 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. */ @@ -1021,12 +1214,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]; @@ -1044,6 +1238,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: @@ -1054,23 +1265,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); @@ -1082,6 +1302,7 @@ get_best_gl_visual (saver_screen_info *ssi) { int result = 0; int wait_status = 0; + pid_t pid = -1; FILE *f = fdopen (in, "r"); unsigned long v = 0; @@ -1090,11 +1311,29 @@ get_best_gl_visual (saver_screen_info *ssi) close (out); /* don't need this one */ *buf = 0; - fgets (buf, sizeof(buf)-1, f); + if (! fgets (buf, sizeof(buf)-1, f)) + *buf = 0; fclose (f); - /* Wait for the child to die. */ - waitpid (-1, &wait_status, 0); + if (! si->prefs.verbose_p) + { + close (errout); + close (errin); + } + + /* 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. */ if (1 == sscanf (buf, "0x%lx %c", &v, &c)) result = (int) v; @@ -1117,12 +1356,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; } }