+ while (1)
+ {
+ int wait_status = 0;
+ pid_t kid;
+
+ errno = 0;
+ kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
+
+ if (si->prefs.debug_p)
+ {
+ if (kid < 0 && errno)
+ fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", progname,
+ (long) kid, errno);
+ else
+ fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", progname,
+ (long) kid);
+ }
+
+ /* 0 means no more children to reap.
+ -1 means error -- except "interrupted system call" isn't a "real"
+ error, so if we get that, we should just try again. */
+ if (kid == 0 ||
+ (kid < 0 && errno != EINTR))
+ break;
+
+ describe_dead_child (si, kid, wait_status);
+ }
+}
+
+
+static void
+describe_dead_child (saver_info *si, pid_t kid, int wait_status)
+{
+ int i;
+ saver_preferences *p = &si->prefs;
+ struct screenhack_job *job = find_job (kid);
+ const char *name = job ? job->name : "<unknown>";
+
+ if (WIFEXITED (wait_status))
+ {
+ int exit_status = WEXITSTATUS (wait_status);
+
+ /* Treat exit code as a signed 8-bit quantity. */
+ if (exit_status & 0x80) exit_status |= ~0xFF;
+
+ /* One might assume that exiting with non-0 means something went wrong.
+ But that loser xswarm exits with the code that it was killed with, so
+ it *always* exits abnormally. Treat abnormal exits as "normal" (don't
+ mention them) if we've just killed the subprocess. But mention them
+ if they happen on their own.
+ */
+ if (!job ||
+ (exit_status != 0 &&
+ (p->verbose_p || job->status != job_killed)))
+ fprintf (stderr,
+ "%s: child pid %lu (%s) exited abnormally (code %d).\n",
+ progname, (unsigned long) kid, name, exit_status);
+ else if (p->verbose_p)
+ printf ("%s: child pid %lu (%s) exited normally.\n",
+ progname, (unsigned long) kid, name);
+
+ if (job)
+ job->status = job_dead;
+ }
+ else if (WIFSIGNALED (wait_status))
+ {
+ if (p->verbose_p ||
+ !job ||
+ job->status != job_killed ||
+ WTERMSIG (wait_status) != SIGTERM)
+ fprintf (stderr, "%s: child pid %lu (%s) terminated with %s.\n",
+ progname, (unsigned long) kid, name,
+ signal_name (WTERMSIG(wait_status)));
+
+ if (job)
+ job->status = job_dead;
+ }
+ else if (WIFSTOPPED (wait_status))
+ {
+ if (p->verbose_p)
+ fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n",
+ progname, (unsigned long) kid, name,
+ signal_name (WSTOPSIG (wait_status)));
+
+ if (job)
+ job->status = job_stopped;
+ }
+ else
+ {
+ fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!",
+ progname, (unsigned long) kid, name);
+ if (job)
+ job->status = job_dead;
+ }
+
+ /* Clear out the pid so that screenhack_running_p() knows it's dead.
+ */
+ if (!job || job->status == job_dead)
+ for (i = 0; i < si->nscreens; i++)
+ {
+ saver_screen_info *ssi = &si->screens[i];
+ if (kid == ssi->pid)
+ ssi->pid = 0;
+ }