-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsubprocs.c
147 lines (119 loc) · 3.36 KB
/
subprocs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* subprocs.c --- choosing, spawning, and killing screenhacks.
*
* xscreensaver, Copyright (c) 1991-2003 Jamie Zawinski <[email protected]>
* Modified: Copyright (c) 2004 William Jon McCann <[email protected]>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
#include "config.h"
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#ifndef ESRCH
# include <errno.h>
#endif
#include <sys/time.h> /* sys/resource.h needs this for timeval */
# include <sys/wait.h> /* for waitpid() and associated macros */
#ifdef VMS
# include <processes.h>
# include <unixio.h> /* for close */
# include <unixlib.h> /* for getpid */
# define pid_t int
# define fork vfork
#endif /* VMS */
#ifndef _POSIX_SOURCE
# define _POSIX_SOURCE
#endif
#include <signal.h> /* for the signal names */
#include <glib.h>
#include "subprocs.h"
#if !defined(SIGCHLD) && defined(SIGCLD)
# define SIGCHLD SIGCLD
#endif
/* Semaphore to temporarily turn the SIGCHLD handler into a no-op.
Don't alter this directly -- use block_sigchld() / unblock_sigchld().
*/
static int block_sigchld_handler = 0;
sigset_t
block_sigchld (void)
{
sigset_t child_set;
sigemptyset (&child_set);
sigaddset (&child_set, SIGCHLD);
sigaddset (&child_set, SIGPIPE);
sigprocmask (SIG_BLOCK, &child_set, 0);
block_sigchld_handler++;
return child_set;
}
void
unblock_sigchld (void)
{
sigset_t child_set;
sigemptyset (&child_set);
sigaddset (&child_set, SIGCHLD);
sigaddset (&child_set, SIGPIPE);
sigprocmask (SIG_UNBLOCK, &child_set, 0);
block_sigchld_handler--;
}
int
signal_pid (int pid,
int signal)
{
int status = -1;
gboolean verbose = TRUE;
if (block_sigchld_handler)
/* This function should not be called from the signal handler. */
abort();
block_sigchld (); /* we control the horizontal... */
status = kill (pid, signal);
if (verbose && status < 0) {
if (errno == ESRCH)
g_message ("Child process %lu was already dead.",
(unsigned long) pid);
else {
char buf [1024];
snprintf (buf, sizeof (buf), "Couldn't kill child process %lu",
(unsigned long) pid);
perror (buf);
}
}
unblock_sigchld ();
if (block_sigchld_handler < 0)
abort ();
return status;
}
#ifndef VMS
void
await_dying_children (int pid,
gboolean debug)
{
while (1) {
int wait_status = 0;
pid_t kid;
errno = 0;
kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED);
if (debug) {
if (kid < 0 && errno)
g_message ("waitpid(%d) ==> %ld (%d)", pid, (long) kid, errno);
else if (kid != 0)
g_message ("waitpid(%d) ==> %ld", pid, (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 && errno != EINTR)
break;
}
}
#else /* VMS */
static void await_dying_children (saver_info *si) { return; }
#endif /* VMS */