Mercurial > hg > xemacs-beta
comparison src/ntproc.c @ 290:c9fe270a4101 r21-0b43
Import from CVS: tag r21-0b43
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:36:47 +0200 |
parents | e11d67e05968 |
children | 33bdb3d4b97f |
comparison
equal
deleted
inserted
replaced
289:6e6992ccc4b6 | 290:c9fe270a4101 |
---|---|
341 return TRUE; | 341 return TRUE; |
342 | 342 |
343 EH_Fail: | 343 EH_Fail: |
344 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); | 344 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); |
345 return FALSE; | 345 return FALSE; |
346 } | |
347 | |
348 /* create_child doesn't know what emacs' file handle will be for waiting | |
349 on output from the child, so we need to make this additional call | |
350 to register the handle with the process | |
351 This way the select emulator knows how to match file handles with | |
352 entries in child_procs. */ | |
353 void | |
354 register_child (int pid, int fd) | |
355 { | |
356 child_process *cp; | |
357 | |
358 cp = find_child_pid (pid); | |
359 if (cp == NULL) | |
360 { | |
361 DebPrint (("register_child unable to find pid %lu\n", pid)); | |
362 return; | |
363 } | |
364 | |
365 #ifdef FULL_DEBUG | |
366 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid)); | |
367 #endif | |
368 | |
369 cp->fd = fd; | |
370 | |
371 /* thread is initially blocked until select is called; set status so | |
372 that select will release thread */ | |
373 cp->status = STATUS_READ_ACKNOWLEDGED; | |
374 | |
375 /* attach child_process to fd_info */ | |
376 if (fd_info[fd].cp != NULL) | |
377 { | |
378 DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd)); | |
379 abort (); | |
380 } | |
381 | |
382 fd_info[fd].cp = cp; | |
383 } | |
384 | |
385 /* When a process dies its pipe will break so the reader thread will | |
386 signal failure to the select emulator. | |
387 The select emulator then calls this routine to clean up. | |
388 Since the thread signaled failure we can assume it is exiting. */ | |
389 static void | |
390 reap_subprocess (child_process *cp) | |
391 { | |
392 if (cp->procinfo.hProcess) | |
393 { | |
394 /* Reap the process */ | |
395 if (WaitForSingleObject (cp->procinfo.hProcess, INFINITE) != WAIT_OBJECT_0) | |
396 DebPrint (("reap_subprocess.WaitForSingleObject (process) failed " | |
397 "with %lu for fd %ld\n", GetLastError (), cp->fd)); | |
398 CloseHandle (cp->procinfo.hProcess); | |
399 cp->procinfo.hProcess = NULL; | |
400 CloseHandle (cp->procinfo.hThread); | |
401 cp->procinfo.hThread = NULL; | |
402 } | |
403 | |
404 /* For asynchronous children, the child_proc resources will be freed | |
405 when the last pipe read descriptor is closed; for synchronous | |
406 children, we must explicitly free the resources now because | |
407 register_child has not been called. */ | |
408 if (cp->fd == -1) | |
409 delete_child (cp); | |
410 } | |
411 | |
412 /* Wait for any of our existing child processes to die | |
413 When it does, close its handle | |
414 Return the pid and fill in the status if non-NULL. */ | |
415 | |
416 int | |
417 sys_wait (int *status) | |
418 { | |
419 DWORD active, retval; | |
420 int nh; | |
421 int pid; | |
422 child_process *cp, *cps[MAX_CHILDREN]; | |
423 HANDLE wait_hnd[MAX_CHILDREN]; | |
424 | |
425 nh = 0; | |
426 if (dead_child != NULL) | |
427 { | |
428 /* We want to wait for a specific child */ | |
429 wait_hnd[nh] = dead_child->procinfo.hProcess; | |
430 cps[nh] = dead_child; | |
431 if (!wait_hnd[nh]) abort (); | |
432 nh++; | |
433 active = 0; | |
434 goto get_result; | |
435 } | |
436 else | |
437 { | |
438 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
439 /* some child_procs might be sockets; ignore them */ | |
440 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | |
441 { | |
442 wait_hnd[nh] = cp->procinfo.hProcess; | |
443 cps[nh] = cp; | |
444 if (!wait_hnd[nh]) abort (); /* Sync with FSF Emacs 19.34.6 note: only in XEmacs */ | |
445 nh++; | |
446 } | |
447 } | |
448 | |
449 if (nh == 0) | |
450 { | |
451 /* Nothing to wait on, so fail */ | |
452 errno = ECHILD; | |
453 return -1; | |
454 } | |
455 | |
456 do | |
457 { | |
458 /* Check for quit about once a second. */ | |
459 QUIT; | |
460 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); | |
461 } while (active == WAIT_TIMEOUT); | |
462 | |
463 if (active == WAIT_FAILED) | |
464 { | |
465 errno = EBADF; | |
466 return -1; | |
467 } | |
468 else if (active >= WAIT_OBJECT_0 && | |
469 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | |
470 { | |
471 active -= WAIT_OBJECT_0; | |
472 } | |
473 else if (active >= WAIT_ABANDONED_0 && | |
474 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | |
475 { | |
476 active -= WAIT_ABANDONED_0; | |
477 } | |
478 else | |
479 abort (); | |
480 | |
481 get_result: | |
482 if (!GetExitCodeProcess (wait_hnd[active], &retval)) | |
483 { | |
484 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", | |
485 GetLastError ())); | |
486 retval = 1; | |
487 } | |
488 if (retval == STILL_ACTIVE) | |
489 { | |
490 /* Should never happen */ | |
491 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); | |
492 errno = EINVAL; | |
493 return -1; | |
494 } | |
495 | |
496 /* Massage the exit code from the process to match the format expected | |
497 by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and | |
498 WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */ | |
499 | |
500 if (retval == STATUS_CONTROL_C_EXIT) | |
501 retval = SIGINT; | |
502 else | |
503 retval <<= 8; | |
504 | |
505 cp = cps[active]; | |
506 pid = cp->pid; | |
507 #ifdef FULL_DEBUG | |
508 DebPrint (("Wait signaled with process pid %d\n", cp->pid)); | |
509 #endif | |
510 | |
511 if (status) | |
512 { | |
513 *status = retval; | |
514 } | |
515 else if (synch_process_alive) | |
516 { | |
517 synch_process_alive = 0; | |
518 | |
519 /* Report the status of the synchronous process. */ | |
520 if (WIFEXITED (retval)) | |
521 synch_process_retcode = WRETCODE (retval); | |
522 else if (WIFSIGNALED (retval)) | |
523 { | |
524 int code = WTERMSIG (retval); | |
525 char *signame = 0; | |
526 | |
527 if (code < NSIG) | |
528 { | |
529 /* Suppress warning if the table has const char *. */ | |
530 signame = (char *) sys_siglist[code]; | |
531 } | |
532 if (signame == 0) | |
533 signame = "unknown"; | |
534 | |
535 synch_process_death = signame; | |
536 } | |
537 | |
538 reap_subprocess (cp); | |
539 } | |
540 | |
541 reap_subprocess (cp); | |
542 | |
543 return pid; | |
544 } | 346 } |
545 | 347 |
546 void | 348 void |
547 win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) | 349 win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) |
548 { | 350 { |