pidgin/gtkmain.c

branch
custom_smiley
changeset 22651
72d47896d80d
parent 22557
a009a7319294
parent 22565
d1943619d6f9
child 22656
c4c7c4852390
equal deleted inserted replaced
22557:a009a7319294 22651:72d47896d80d
98 SIGHUP, 98 SIGHUP,
99 SIGINT, 99 SIGINT,
100 SIGTERM, 100 SIGTERM,
101 SIGQUIT, 101 SIGQUIT,
102 SIGCHLD, 102 SIGCHLD,
103 SIGALRM,
104 -1 103 -1
105 }; 104 };
106 105
107 static const int ignore_sig_list[] = { 106 static const int ignore_sig_list[] = {
108 SIGPIPE, 107 SIGPIPE,
139 } 138 }
140 139
141 #ifdef HAVE_SIGNAL_H 140 #ifdef HAVE_SIGNAL_H
142 static void sighandler(int sig); 141 static void sighandler(int sig);
143 142
144 /** 143 /*
145 * Reap all our dead children. Sometimes libpurple forks off a separate 144 * This child process reaping stuff is currently only used for processes that
146 * process to do some stuff. When that process exits we are 145 * were forked to play sounds. It's not needed for forked DNS child, which
147 * informed about it so that we can call waitpid() and let it 146 * have their own waitpid() call. It might be wise to move this code into
148 * stop being a zombie. 147 * gtksound.c.
149 *
150 * We used to do this immediately when our signal handler was
151 * called, but because of GStreamer we now wait one second before
152 * reaping anything. Why? For some reason GStreamer fork()s
153 * during their initialization process. I don't understand why...
154 * but they do it, and there's nothing we can do about it.
155 *
156 * Anyway, so then GStreamer waits for its child to die and then
157 * it continues with the initialization process. This means that
158 * we have a race condition where GStreamer is waitpid()ing for its
159 * child to die and we're catching the SIGCHLD signal. If GStreamer
160 * is awarded the zombied process then everything is ok. But if libpurple
161 * reaps the zombie process then the GStreamer initialization sequence
162 * fails.
163 *
164 * So the ugly solution is to wait a second to give GStreamer time to
165 * reap that bad boy.
166 *
167 * GStreamer 0.10.10 and newer have a gst_register_fork_set_enabled()
168 * function that can be called by applications to disable forking
169 * during initialization. But it's not in 0.10.0, so we shouldn't
170 * use it.
171 *
172 * All of this child process reaping stuff is currently only used for
173 * processes that were forked to play sounds. It's not needed for
174 * forked DNS child, which have their own waitpid() call. It might
175 * be wise to move this code into gtksound.c.
176 */ 148 */
177 static void 149 static void
178 clean_pid(void) 150 clean_pid(void)
179 { 151 {
180 int status; 152 int status;
187 if ((pid == (pid_t) - 1) && (errno != ECHILD)) { 159 if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
188 char errmsg[BUFSIZ]; 160 char errmsg[BUFSIZ];
189 snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid); 161 snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
190 perror(errmsg); 162 perror(errmsg);
191 } 163 }
192
193 /* Restore signal catching */
194 signal(SIGALRM, sighandler);
195 } 164 }
196 165
197 char *segfault_message; 166 char *segfault_message;
198 167
199 /* 168 /*
219 case SIGSEGV: 188 case SIGSEGV:
220 fprintf(stderr, "%s", segfault_message); 189 fprintf(stderr, "%s", segfault_message);
221 abort(); 190 abort();
222 break; 191 break;
223 case SIGCHLD: 192 case SIGCHLD:
224 /* Restore signal catching */
225 signal(SIGCHLD, sighandler);
226 alarm(1);
227 break;
228 case SIGALRM:
229 clean_pid(); 193 clean_pid();
194 signal(SIGCHLD, sighandler); /* restore signal catching on this one! */
230 break; 195 break;
231 default: 196 default:
232 purple_debug_warning("sighandler", "Caught signal %d\n", sig); 197 purple_debug_warning("sighandler", "Caught signal %d\n", sig);
233 purple_connections_disconnect_all(); 198 purple_connections_disconnect_all();
234 199

mercurial