Mercurial > hg > xemacs-beta
comparison src/sysdep.c @ 163:0132846995bd r20-3b8
Import from CVS: tag r20-3b8
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:43:35 +0200 |
parents | 6b37e6ddd302 |
children | 2d532a89d707 |
comparison
equal
deleted
inserted
replaced
162:4de2936b4e77 | 163:0132846995bd |
---|---|
224 } | 224 } |
225 #endif /* BSD */ | 225 #endif /* BSD */ |
226 | 226 |
227 #endif /* NO_SUBPROCESSES */ | 227 #endif /* NO_SUBPROCESSES */ |
228 | 228 |
229 int wait_debugging; /* Set nonzero to make following function work under dbx | |
230 (at least for bsd). */ | |
231 | |
232 /* Wait for subprocess with process id `pid' to terminate and | |
233 make sure it will get eliminated (not remain forever as a zombie). */ | |
234 | 229 |
235 void | 230 void |
236 wait_for_termination (int pid) | 231 wait_for_termination (int pid) |
237 { | 232 { |
238 /* #### With the new improved SIGCHLD handling stuff, there is much | 233 /* #### With the new improved SIGCHLD handling stuff, there is much |
239 less danger of race conditions and some of the comments below | 234 less danger of race conditions and some of the comments below |
240 don't apply. This should be updated. */ | 235 don't apply. This should be updated. */ |
236 | |
237 #if defined (NO_SUBPROCESSES) | |
241 while (1) | 238 while (1) |
242 { | 239 { |
243 #if !defined (NO_SUBPROCESSES) | 240 /* No need to be tricky like below; we can just call wait(). */ |
244 # ifdef VMS | 241 /* #### should figure out how to write a wait_allowing_quit(). |
245 int status; | 242 Since hardly any systems don't have subprocess support, |
246 | 243 however, there doesn't seem to be much point. */ |
247 status = SYS$FORCEX (&pid, 0, 0); | 244 if (wait (0) == pid) |
248 return; | 245 return; |
249 # else /* not VMS */ | 246 } |
250 /* Note that, whenever any subprocess terminates (asynch. or synch.), | 247 #elif defined (VMS) |
251 the SIGCHLD handler will be called and it will call wait(). | 248 int status = SYS$FORCEX (&pid, 0, 0); |
252 Thus we cannot just call wait() ourselves, and we can't block | 249 return; |
253 SIGCHLD and then call wait(), because then if an asynch. | 250 |
254 process dies while we're waiting for our synch. process, | 251 #elif defined (HAVE_WAITPID) |
255 Emacs will never notice that the asynch. process died. | 252 /* Note that, whenever any subprocess terminates (asynch. or synch.), |
256 | 253 the SIGCHLD handler will be called and it will call wait(). Thus |
257 So, the general approach we take is to repeatedly block until | 254 we cannot just call wait() ourselves, and we can't block SIGCHLD |
258 a signal arrives, and then check if our process died | 255 and then call wait(), because then if an asynch. process dies |
259 using kill (pid, 0). (We could also check the value of | 256 while we're waiting for our synch. process, Emacs will never |
260 `synch_process_alive', since the SIGCHLD handler will reset | 257 notice that the asynch. process died. |
261 that and we know that we're only being called on synchronous | 258 |
262 processes, but this approach is safer. I don't trust | 259 So, the general approach we take is to repeatedly block until a |
263 the proper delivery of SIGCHLD. | 260 signal arrives, and then check if our process died using kill |
264 | 261 (pid, 0). (We could also check the value of `synch_process_alive', |
265 Note also that we cannot use any form of waitpid(). | 262 since the SIGCHLD handler will reset that and we know that we're |
266 A loop with WNOHANG will chew up CPU time; better to | 263 only being called on synchronous processes, but this approach is |
267 use sleep(). A loop without WNOWAIT will screw up | 264 safer. I don't trust the proper delivery of SIGCHLD. |
268 the SIGCHLD handler (actually this is not true, if you | 265 |
269 duplicate the exit-status-reaping code; see below). | 266 Note also that we cannot use any form of waitpid(). A loop with |
270 A loop with WNOWAIT will result in a race condition | 267 WNOHANG will chew up CPU time; better to use sleep(). A loop |
271 if the process terminates between the process-status | 268 without WNOWAIT will screw up the SIGCHLD handler (actually this |
272 check and the call to waitpid(). */ | 269 is not true, if you duplicate the exit-status-reaping code; see |
273 | 270 below). A loop with WNOWAIT will result in a race condition if |
274 /* Formerly, immediate_quit was set around this function call, | 271 the process terminates between the process-status check and the |
275 but that could lead to problems if the QUIT happened when | 272 call to waitpid(). */ |
276 SIGCHLD was blocked -- it would remain blocked. Yet another | 273 |
277 reason why immediate_quit is a bad idea. In any case, there | 274 /* Formerly, immediate_quit was set around this function call, but |
278 is no reason to resort to this because either the SIGIO or | 275 that could lead to problems if the QUIT happened when SIGCHLD was |
279 the SIGALRM will stop the block in EMACS_WAIT_FOR_SIGNAL(). */ | 276 blocked -- it would remain blocked. Yet another reason why |
277 immediate_quit is a bad idea. In any case, there is no reason to | |
278 resort to this because either the SIGIO or the SIGALRM will stop | |
279 the block in EMACS_WAIT_FOR_SIGNAL(). */ | |
280 | |
281 /* Apparently there are bugs on some systems with the second method | |
282 used below (the EMACS_BLOCK_SIGNAL method), whereby zombie | |
283 processes get left around. It appears in those cases that the | |
284 SIGCHLD handler is never getting invoked. It's not clear whether | |
285 this is an Emacs bug or a kernel bug or both: on HPUX this | |
286 problem is observed only with XEmacs, but under Solaris 2.4 all | |
287 sorts of different programs have problems with zombies. The | |
288 method we use here does not require a working SIGCHLD (but will | |
289 not break if it is working), and should be safe. */ | |
290 /* | |
291 We use waitpid(), contrary to the remarks above. There is no | |
292 race condition, because the three situations when sigchld_handler | |
293 is invoked should be handled OK: | |
294 | |
295 - handler invoked before waitpid(): In this case, subprocess | |
296 status will be set by sigchld_handler. waitpid() here will | |
297 return -1 with errno set to ECHILD, which is a valid exit | |
298 condition. | |
299 | |
300 - handler invoked during waitpid(): as above, except that errno | |
301 here will be set to EINTR. This will cause waitpid() to be | |
302 called again, and this time it will exit with ECHILD. | |
303 | |
304 - handler invoked after waitpid(): The following code will reap | |
305 the subprocess. In the handler, wait() will return -1 because | |
306 there is no child to reap, and the handler will exit without | |
307 modifying child subprocess status. */ | |
308 int ret, status; | |
309 | |
310 /* Because the SIGCHLD handler can potentially reap the synchronous | |
311 subprocess, we should take care of that. */ | |
312 | |
313 /* Will stay in the do loop as long as: | |
314 1. Process is alive | |
315 2. Ctrl-G is not pressed */ | |
316 do | |
317 { | |
280 QUIT; | 318 QUIT; |
281 # ifdef HAVE_WAITPID | 319 ret = waitpid (pid, &status, 0); |
282 /* Apparently there are bugs on some systems with the second | 320 /* waitpid returns 0 if the process is still alive. */ |
283 method used below (the EMACS_BLOCK_SIGNAL method), whereby | 321 } |
284 zombie processes get left around. It appears in those cases | 322 while (ret == 0 || (ret == -1 && errno == EINTR)); |
285 that the SIGCHLD handler is never getting invoked. It's | 323 |
286 not clear whether this is an Emacs bug or a kernel bug or | 324 if (ret == pid) /* Success */ |
287 both: on HPUX this problem is observed only with XEmacs, | 325 /* Set synch process globals. This is can also happen |
288 but under Solaris 2.4 all sorts of different programs have | 326 in sigchld_handler, and that code is duplicated. */ |
289 problems with zombies. The method we use here does not | 327 { |
290 require a working SIGCHLD (but will not break if it is | 328 synch_process_alive = 0; |
291 working), and should be safe. */ | 329 if (WIFEXITED (status)) |
292 /* | 330 synch_process_retcode = WEXITSTATUS (status); |
293 We use waitpid() contrary to the remarks above. There is | 331 else if (WIFSIGNALED (status)) |
294 no race condition, because the three situations when | 332 synch_process_death = signal_name (WTERMSIG (status)); |
295 sigchld_handler is invoked should be handled OK: | 333 } |
296 - handler invoked before waitpid(): In this case, subprocess | 334 /* On exiting the loop, ret will be -1, with errno set to ECHILD if |
297 status will be set by sigchld_handler. waitpid() here will | 335 the child has already been reaped, e.g. in the signal handler. */ |
298 return -1 with errno set to ECHILD, which is a valid | 336 |
299 exit condition. | 337 /* Otherwise, we've had some error condition here. |
300 | 338 Per POSIX, the only other possibilities are: |
301 - handler invoked during waitpid(): as above, except that | 339 - EFAULT (bus error accessing arg 2) or |
302 errno here will be set to EINTR. This will cause waitpid() to | 340 - EINVAL (incorrect arguments), |
303 be called again, and this time it will exit with ECHILD. | 341 which are both program bugs. |
304 | 342 |
305 - handler invoked after waitpid(): The following code will reap | 343 Since implementations may add their own error indicators on top, |
306 the subprocess. In the handler, wait() will return -1 | 344 we ignore it by default. */ |
307 because there is no child to reap, and the handler will exit | 345 #elif defined (EMACS_BLOCK_SIGNAL) && !defined (BROKEN_WAIT_FOR_SIGNAL) && defined (SIGCHLD) |
308 without modifying child subprocess status. | 346 while (1) |
309 */ | 347 { |
310 { | 348 static int wait_debugging = 0; /* Set nonzero to make following |
311 /* Because the SIGCHLD handler can potentially reap the | 349 function work under dbx (at least for bsd). */ |
312 synchronous subprocess, we should take care of that. */ | 350 QUIT; |
313 | 351 if (wait_debugging) |
314 int ret; | 352 return; |
315 int w; | 353 |
316 /* Will stay in the do loop as long as: | 354 EMACS_BLOCK_SIGNAL (SIGCHLD); |
317 1. Process is alive | 355 /* Block SIGCHLD from happening during this check, |
318 2. Ctrl-G is not pressed */ | 356 to avoid race conditions. */ |
319 do | 357 if (kill (pid, 0) < 0) |
320 { | |
321 QUIT; | |
322 ret = waitpid (pid, &w, 0); | |
323 /* waitpid returns 0 if the process is still alive. */ | |
324 } | |
325 while (ret == 0 || (ret == -1 && errno == EINTR)); | |
326 | |
327 /* On exiting the loop, ret will be -1, with errno set to | |
328 ECHILD if the child has already been reaped, eg in the | |
329 signal handler. */ | |
330 | |
331 if (! (ret == pid || (ret == -1 && errno == ECHILD))) | |
332 { | |
333 /* We've had some error condition here. Per POSIX, the | |
334 only other possibilities are: | |
335 EFAULT (bus error accessing arg 2) or EINVAL (incorrect | |
336 arguments), which are both program bugs. | |
337 | |
338 Since implementations may add their own error | |
339 indicators on top, we ignore it by default. | |
340 */ | |
341 | |
342 break; | |
343 } | |
344 | |
345 /* Set synch process globals. This is can also happen | |
346 in sigchld_handler, and that code is duplicated. */ | |
347 if (ret == pid) | |
348 { /* Update the global sigchld stats. */ | |
349 synch_process_alive = 0; | |
350 if (WIFEXITED (w)) | |
351 synch_process_retcode = WEXITSTATUS (w); | |
352 else if (WIFSIGNALED (w)) | |
353 synch_process_death = signal_name (WTERMSIG (w)); | |
354 } | |
355 break; | |
356 } | |
357 # elif defined (EMACS_BLOCK_SIGNAL) && !defined (BROKEN_WAIT_FOR_SIGNAL) && defined (SIGCHLD) | |
358 if (!wait_debugging) | |
359 { | 358 { |
360 EMACS_BLOCK_SIGNAL (SIGCHLD); | 359 EMACS_UNBLOCK_SIGNAL (SIGCHLD); |
361 /* Block SIGCHLD from happening during this check, | 360 return; |
362 to avoid race conditions. */ | |
363 if (kill (pid, 0) < 0) | |
364 { | |
365 EMACS_UNBLOCK_SIGNAL (SIGCHLD); | |
366 return; | |
367 } | |
368 else | |
369 /* WARNING: Whatever this macro does *must* not allow SIGCHLD | |
370 to happen between the time that it's reenabled and when we | |
371 begin to block. Otherwise we may end up blocking for a | |
372 signal that has already arrived and isn't coming again. | |
373 Can you say "race condition"? | |
374 | |
375 I assume that the system calls sigpause() or sigsuspend() | |
376 to provide this atomicness. If you're getting hangs in | |
377 sigpause()/sigsuspend(), then your OS doesn't | |
378 implement this properly (this applies under hpux9, | |
379 for example). Try defining BROKEN_WAIT_FOR_SIGNAL. */ | |
380 EMACS_WAIT_FOR_SIGNAL (SIGCHLD); | |
381 continue; | |
382 } | 361 } |
383 # else /* not HAVE_WAITPID and (not EMACS_BLOCK_SIGNAL or | 362 else |
384 BROKEN_WAIT_FOR_SIGNAL) */ | 363 /* WARNING: Whatever this macro does *must* not allow SIGCHLD |
385 /* This approach is kind of cheesy but is guaranteed(?!) to work | 364 to happen between the time that it's reenabled and when we |
386 for all systems. */ | 365 begin to block. Otherwise we may end up blocking for a |
366 signal that has already arrived and isn't coming again. | |
367 Can you say "race condition"? | |
368 | |
369 I assume that the system calls sigpause() or sigsuspend() | |
370 to provide this atomicness. If you're getting hangs in | |
371 sigpause()/sigsuspend(), then your OS doesn't implement | |
372 this properly (this applies under hpux9, for example). | |
373 Try defining BROKEN_WAIT_FOR_SIGNAL. */ | |
374 EMACS_WAIT_FOR_SIGNAL (SIGCHLD); | |
375 } | |
376 #else /* not HAVE_WAITPID and (not EMACS_BLOCK_SIGNAL or BROKEN_WAIT_FOR_SIGNAL) */ | |
377 /* This approach is kind of cheesy but is guaranteed(?!) to work | |
378 for all systems. */ | |
379 while (1) | |
380 { | |
381 QUIT; | |
387 if (kill (pid, 0) < 0) | 382 if (kill (pid, 0) < 0) |
388 return; | 383 return; |
389 emacs_sleep (1); | 384 emacs_sleep (1); |
390 # endif /* not HAVE_WAITPID and (not EMACS_BLOCK_SIGNAL or | 385 } |
391 BROKEN_WAIT_FOR_SIGNAL) */ | 386 #endif /* OS features */ |
392 # endif /* not VMS */ | |
393 #else /* NO_SUBPROCESSES */ | |
394 /* No need to be tricky like above; we can just call wait(). */ | |
395 int status; | |
396 /* #### should figure out how to write a wait_allowing_quit(). | |
397 Since hardly any systems don't have subprocess support, | |
398 however, there doesn't seem to be much point. */ | |
399 status = wait (0); | |
400 if (status == pid) | |
401 return; | |
402 #endif /* NO_SUBPROCESSES */ | |
403 } | |
404 } | 387 } |
405 | 388 |
406 | 389 |
407 #if !defined (NO_SUBPROCESSES) | 390 #if !defined (NO_SUBPROCESSES) |
408 | 391 |
3297 /* Emulations of missing system calls */ | 3280 /* Emulations of missing system calls */ |
3298 /************************************************************************/ | 3281 /************************************************************************/ |
3299 | 3282 |
3300 /***** (these are primarily required for USG, it seems) *****/ | 3283 /***** (these are primarily required for USG, it seems) *****/ |
3301 | 3284 |
3285 #ifndef HAVE_GETCWD | |
3286 char * | |
3287 getcwd (char *pathname, int size) | |
3288 { | |
3289 return getwd (pathname); | |
3290 } | |
3291 #endif /* emulate getcwd */ | |
3292 | |
3293 | |
3294 #if 0 /* mrb */ | |
3302 /* | 3295 /* |
3303 * Warning, this function may not duplicate BSD 4.2 action properly | 3296 * Warning, this function may not duplicate BSD 4.2 action properly |
3304 * under error conditions. | 3297 * under error conditions. |
3305 */ | 3298 */ |
3306 | 3299 |
3323 strcpy (pathname, npath); | 3316 strcpy (pathname, npath); |
3324 xfree (spath); /* getcwd uses malloc */ | 3317 xfree (spath); /* getcwd uses malloc */ |
3325 return pathname; | 3318 return pathname; |
3326 } | 3319 } |
3327 #endif /* HAVE_GETWD */ | 3320 #endif /* HAVE_GETWD */ |
3321 #endif /* 0 - mrb */ | |
3328 | 3322 |
3329 /* | 3323 /* |
3330 * Emulate rename using unlink/link. Note that this is | 3324 * Emulate rename using unlink/link. Note that this is |
3331 * only partially correct. Also, doesn't enforce restriction | 3325 * only partially correct. Also, doesn't enforce restriction |
3332 * that files be of same type (regular->regular, dir->dir, etc). | 3326 * that files be of same type (regular->regular, dir->dir, etc). |