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 {