pidgin/gtkmain.c

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

mercurial