From 164a681ca55419ec2cc7c9ad45f720f4a79cada1 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 9 Oct 2000 02:53:44 +0000 Subject: [PATCH] * dtable.cc (set_std_handle): Use std_consts array to control SetStdHandle settings. (dtable::fixup_after_fork): Ditto. * exceptions.cc (set_sig_errno): Remove some debugging output. * path.cc (path_conv::check): Don't OR need_directory with flags sent to symlink_info::check. (symlink_info::check): Use PATH_ALL_EXEC to determine when a file is executable. * path.h (path_types): Add PATH_ALL_EXEC. (isexec): Use PATH_ALL_EXEC so that cygexec types will be considered executable. * pinfo.h (_pinfo): Add a process handle that is kept open throughout the life of a cygwin pid. * sigproc.cc (proc_exists): Remove hopefully obsolete stuff. (proc_subproc): Set up process handle that is kept open throughout the life of a cygwin pid. Reorganize PROC_WAIT stuff to use common code. (proc_terminate): Close pid lifetime process handle. (checkstate): Cleanup. (stopped_or_terminated): Move zombie cleanup. (remove_zombie): To here. * spawn.cc (spawn_guts): Reorganize reparenting code for 1247th time. --- winsup/cygwin/ChangeLog | 24 ++++++ winsup/cygwin/dtable.cc | 19 +++-- winsup/cygwin/exceptions.cc | 2 +- winsup/cygwin/path.cc | 4 +- winsup/cygwin/path.h | 3 +- winsup/cygwin/pinfo.cc | 1 + winsup/cygwin/pinfo.h | 3 + winsup/cygwin/sigproc.cc | 154 +++++++++++++++--------------------- winsup/cygwin/spawn.cc | 60 +++++++------- 9 files changed, 138 insertions(+), 132 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7f3929614..cd766e5ee 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,27 @@ +Sun Oct 8 22:38:40 2000 Christopher Faylor + + * dtable.cc (set_std_handle): Use std_consts array to control + SetStdHandle settings. + (dtable::fixup_after_fork): Ditto. + * exceptions.cc (set_sig_errno): Remove some debugging output. + * path.cc (path_conv::check): Don't OR need_directory with flags sent + to symlink_info::check. + (symlink_info::check): Use PATH_ALL_EXEC to determine when a file is + executable. + * path.h (path_types): Add PATH_ALL_EXEC. + (isexec): Use PATH_ALL_EXEC so that cygexec types will be considered + executable. + * pinfo.h (_pinfo): Add a process handle that is kept open throughout + the life of a cygwin pid. + * sigproc.cc (proc_exists): Remove hopefully obsolete stuff. + (proc_subproc): Set up process handle that is kept open throughout the + life of a cygwin pid. Reorganize PROC_WAIT stuff to use common code. + (proc_terminate): Close pid lifetime process handle. + (checkstate): Cleanup. + (stopped_or_terminated): Move zombie cleanup. + (remove_zombie): To here. + * spawn.cc (spawn_guts): Reorganize reparenting code for 1247th time. + Sat Oct 7 13:59:15 2000 Christopher Faylor * fhandler.h (fhandler_base): Remove obsolete _rpos and _rsize diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index 5eff4fd66..f149d562b 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -33,6 +33,9 @@ details. */ dtable fdtab; +static DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, + STD_ERROR_HANDLE}; + /* Set aside space for the table of fds */ void dtable_init (void) @@ -45,11 +48,9 @@ void __stdcall set_std_handle (int fd) { if (fd == 0) - SetStdHandle (STD_INPUT_HANDLE, fdtab[fd]->get_handle ()); - else if (fd == 1) - SetStdHandle (STD_OUTPUT_HANDLE, fdtab[fd]->get_output_handle ()); - else if (fd == 2) - SetStdHandle (STD_ERROR_HANDLE, fdtab[fd]->get_output_handle ()); + SetStdHandle (std_consts[fd], fdtab[fd]->get_handle ()); + else if (fd <= 2) + SetStdHandle (std_consts[fd], fdtab[fd]->get_output_handle ()); } int @@ -453,7 +454,13 @@ dtable::fixup_after_exec (HANDLE parent, size_t sz, fhandler_base **f) if (fds[i]->get_close_on_exec ()) release (i); else - fds[i]->fixup_after_exec (parent); + { + fds[i]->fixup_after_exec (parent); + if (i == 0) + SetStdHandle (std_consts[i], fds[i]->get_io_handle ()); + else if (i <= 2) + SetStdHandle (std_consts[i], fds[i]->get_output_handle ()); + } } } diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 187e937a7..b536d6685 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -688,7 +688,7 @@ set_sig_errno (int e) { set_errno (e); sigsave.saved_errno = e; - debug_printf ("errno %d", e); + // sigproc_printf ("errno %d", e); } #define SUSPEND_TRIES 10000 diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index fb8bcd5dd..41a0a7f16 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -257,7 +257,7 @@ path_conv::check (const char *src, unsigned opt, else { suff = suffixes; - sym.pflags = path_flags | need_directory; + sym.pflags = path_flags; } int len = sym.check (path_copy, suff); @@ -2294,7 +2294,7 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes) else { /* Not a symlink, see if executable. */ - if (!(pflags & (PATH_EXEC | PATH_CYGWIN_EXEC)) && got >= 2 && + if (!(pflags & PATH_ALL_EXEC) && got >= 2 && ((cookie_buf[0] == '#' && cookie_buf[1] == '!') || (cookie_buf[0] == ':' && cookie_buf[1] == '\n') || (cookie_buf[0] == 'M' && cookie_buf[1] == 'Z'))) diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 4c7f2c0e2..3baa6a6cb 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -36,6 +36,7 @@ enum path_types PATH_BINARY = MOUNT_BINARY, PATH_EXEC = MOUNT_EXEC, PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, + PATH_ALL_EXEC = PATH_CYGWIN_EXEC | PATH_EXEC, PATH_SOCKET = 0x40000000, PATH_HASACLS = 0x80000000 }; @@ -52,7 +53,7 @@ class path_conv int isbinary () {return path_flags & PATH_BINARY;} int issymlink () {return path_flags & PATH_SYMLINK;} int issocket () {return path_flags & PATH_SOCKET;} - int isexec () {return path_flags & PATH_EXEC;} + int isexec () {return path_flags & PATH_ALL_EXEC;} int iscygexec () {return path_flags & PATH_CYGWIN_EXEC;} void set_binary () {path_flags |= PATH_BINARY;} diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index f7c233da6..1ce6ace2c 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -258,6 +258,7 @@ pinfo::init (pid_t n, DWORD create, HANDLE in_h) destroy = 1; } + void pinfo::release () { diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 13eaa1de8..2c5b862c6 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -41,6 +41,9 @@ public: #define PINFO_REDIR_SIZE ((DWORD) &(((_pinfo *)NULL)->hProcess) + sizeof (DWORD)) + /* Handle associated with initial Windows pid which started it all. */ + HANDLE pid_handle; + /* Parent process id. */ pid_t ppid; diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 99ed89ce9..f4929f109 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -236,6 +236,7 @@ proc_exists (_pinfo *p) } sigproc_printf ("it doesn't exist"); +#if 0 /* If the parent pid does not exist, clean this process out of the pinfo * table. It must have died abnormally. */ @@ -244,6 +245,7 @@ proc_exists (_pinfo *p) p->hProcess = NULL; p->process_state = PID_NOT_IN_USE; } +#endif return FALSE; } @@ -303,11 +305,15 @@ proc_subproc (DWORD what, DWORD val) pchildren[nchildren] = vchild; hchildren[nchildren] = vchild->hProcess; ProtectHandle1 (vchild->hProcess, childhProc); + nchildren++; + if (!DuplicateHandle (hMainProc, vchild->hProcess, hMainProc, &vchild->pid_handle, + 0, 0, DUPLICATE_SAME_ACCESS)) + system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid); + ProtectHandle1 (vchild->pid_handle, pid_handle); sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p", vchild->pid, nchildren, vchild->dwProcessId, vchild->hProcess); - nchildren++; wake_wait_subproc (); break; @@ -351,6 +357,38 @@ proc_subproc (DWORD what, DWORD val) clearing = 0; goto scan_wait; + /* Handle a wait4() operation. Allocates an event for the calling + * thread which is signaled when the appropriate pid exits or stops. + * (usually called from the main thread) + */ + case PROC_WAIT: + wval->ev = NULL; // Don't know event flag yet + + if (wval->pid <= 0) + child = NULL; // Not looking for a specific pid + else if (!mychild (wval->pid)) + goto out; // invalid pid. flag no such child + + wval->status = 0; // Don't know status yet + sigproc_printf ("wval->pid %d, wval->options %d", wval->pid, wval->options); + + /* If the first time for this thread, create a new event, otherwise + * reset the event. + */ + if ((wval->ev = wval->thread_ev) == NULL) + { + wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, + FALSE, NULL); + ProtectHandle (wval->ev); + } + + ResetEvent (wval->ev); + w = waitq_head.next; + waitq_head.next = wval; /* Add at the beginning. */ + wval->next = w; /* Link in rest of the list. */ + clearing = 0; + goto scan_wait; + /* Clear all waiting threads. Called from exceptions.cc prior to * the main thread's dispatch to a signal handler function. * (called from wait_sig thread) @@ -371,12 +409,13 @@ proc_subproc (DWORD what, DWORD val) { if ((potential_match = checkstate (w)) > 0) sigproc_printf ("released waiting thread"); - else if (!clearing && potential_match < 0) + else if (!clearing && !(w->next->options & WNOHANG) && potential_match < 0) sigproc_printf ("only found non-terminated children"); else if (potential_match <= 0) // nothing matched { sigproc_printf ("waiting thread found no children"); HANDLE oldw = w->next->ev; + w->next->pid = 0; if (clearing) w->next->status = -1; /* flag that a signal was received */ else @@ -397,75 +436,6 @@ proc_subproc (DWORD what, DWORD val) sigproc_printf ("finished clearing"); } break; - - /* Handle a wait4() operation. Allocates an event for the calling - * thread which is signaled when the appropriate pid exits or stops. - * (usually called from the main thread) - */ - case PROC_WAIT: - wval->ev = NULL; // Don't know event flag yet - - if (wval->pid <= 0) - child = NULL; // Not looking for a specific pid - else if (!mychild (wval->pid)) - goto out; // invalid pid. flag no such child - - wval->status = 0; // Don't know status yet - - /* Put waitq structure at the end of a linked list. */ - for (w = &waitq_head; w->next != NULL; w = w->next) - if (w->next == wval && (w->next = w->next->next) == NULL) - break; - - wval->next = NULL; /* This will be last in the list */ - sigproc_printf ("wval->pid %d, wval->options %d", wval->pid, wval->options); - - /* If the first time for this thread, create a new event, otherwise - * reset the event. - */ - if ((wval->ev = wval->thread_ev) == NULL) - { - wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, - FALSE, NULL); - ProtectHandle (wval->ev); - } - ResetEvent (wval->ev); - - /* Scan list of children to see if any have died. - * If so, the event flag is set so that the wait* () - * process will return immediately. - * - * If no children were found and the wait option was WNOHANG, - * then set the pid to 0 and remove the waitq value from - * consideration. - */ - w->next = wval; /* set at end of wait queue */ - if ((potential_match = checkstate (w)) <= 0) - { - if (!potential_match) - { - w->next = NULL; // don't want to keep looking - wval->ev = NULL; // flag that there are no children - sigproc_printf ("no appropriate children, %p, %p", - wval->thread_ev, wval->ev); - } - else if (wval->options & WNOHANG) - { - w->next = NULL; // don't want to keep looking - wval->pid = 0; // didn't find a pid - if (!SetEvent (wval->ev)) // wake up wait4 () immediately - system_printf ("Couldn't wake up wait event, %E"); - sigproc_printf ("WNOHANG and no terminated children, %p, %p", - wval->thread_ev, wval->ev); - } - } - if (w->next != NULL) - sigproc_printf ("wait activated %p, %p", wval->thread_ev, wval->ev); - else if (wval->ev != NULL) - sigproc_printf ("wait activated %p. Reaped zombie.", wval->ev); - else - sigproc_printf ("wait not activated %p, %p", wval->thread_ev, wval->ev); - break; } out: @@ -513,7 +483,7 @@ proc_terminate (void) if (zombies[i]->hProcess) { ForceCloseHandle1 (zombies[i]->hProcess, childhProc); - zombies[i]->hProcess = NULL; + ForceCloseHandle1 (zombies[i]->pid_handle, pid_handle); } zombies[i]->process_state = PID_NOT_IN_USE; /* CGF FIXME - still needed? */ zombies[i].release(); // FIXME: this breaks older gccs for some reason @@ -530,7 +500,6 @@ proc_terminate (void) else { ForceCloseHandle1 (pchildren[i]->hProcess, childhProc); - pchildren[i]->hProcess = NULL; if (!proc_exists (pchildren[i])) { sigproc_printf ("%d(%d) doesn't exist", pchildren[i]->pid, @@ -937,21 +906,22 @@ init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready) * terminated. */ static int __stdcall -checkstate (waitq *w) +checkstate (waitq *parent_w) { - int i, x, potential_match = 0; - _pinfo *child; + int potential_match = 0; sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies); /* Check already dead processes first to see if they match the criteria * given in w->next. */ - for (i = 0; i < nzombies; i++) - if ((x = stopped_or_terminated (w, child = zombies[i])) < 0) - potential_match = -1; - else if (x > 0) + for (int i = 0; i < nzombies; i++) + switch (stopped_or_terminated (parent_w, zombies[i])) { + case -1: + potential_match = -1; + break; + case 1: remove_zombie (i); potential_match = 1; goto out; @@ -960,13 +930,15 @@ checkstate (waitq *w) sigproc_printf ("checking alive children"); /* No dead terminated children matched. Check for stopped children. */ - for (i = 0; i < nchildren; i++) - if ((x = stopped_or_terminated (w, pchildren[i])) < 0) - potential_match = -1; - else if (x > 0) + for (int i = 0; i < nchildren; i++) + switch (stopped_or_terminated (parent_w, pchildren[i])) { - potential_match = 1; + case -1: + potential_match = -1; break; + case 1: + potential_match = 1; + goto out; } out: @@ -1074,10 +1046,15 @@ static void __stdcall remove_zombie (int ci) { sigproc_printf ("removing %d, pid %d, nzombies %d", ci, zombies[ci]->pid, - nzombies); + nzombies); if (zombies[ci]) - zombies[ci].release (); + { + ForceCloseHandle1 (zombies[ci]->hProcess, childhProc); + ForceCloseHandle1 (zombies[ci]->pid_handle, pid_handle); + zombies[ci]->process_state = PID_NOT_IN_USE; /* a reaped child */ + zombies[ci].release (); + } if (ci < --nzombies) zombies[ci] = zombies[nzombies]; @@ -1146,9 +1123,6 @@ stopped_or_terminated (waitq *parent_w, _pinfo *child) add_rusage ((struct rusage *) w->rusage, &child->rusage_children); add_rusage ((struct rusage *) w->rusage, &child->rusage_self); } - ForceCloseHandle1 (child->hProcess, childhProc); - child->hProcess = NULL; - child->process_state = PID_NOT_IN_USE; /* a reaped child */ } if (!SetEvent (w->ev)) /* wake up wait4 () immediately */ diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 01a9cecd3..8542ecb1e 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -687,14 +687,11 @@ skip_arg_parsing: /* We print the original program name here so the user can see that too. */ syscall_printf ("%d = spawn_guts (%s, %.132s)", - rc ? cygpid : (unsigned int) -1, - prog_arg, one_line.buf); + rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf); - MALLOC_CHECK; /* Name the handle similarly to proc_subproc. */ ProtectHandle1 (pi.hProcess, childhProc); ProtectHandle (pi.hThread); - MALLOC_CHECK; if (mode == _P_OVERLAY) { @@ -785,20 +782,16 @@ skip_arg_parsing: { case WAIT_OBJECT_0: sigproc_printf ("subprocess exited"); - if (!GetExitCodeProcess (pi.hProcess, &res)) - res = 1; + DWORD exitcode; + if (!GetExitCodeProcess (pi.hProcess, &exitcode)) + exitcode = 1; + res |= exitcode; exited = TRUE; - if (nwait <= 2 || mode != _P_OVERLAY) + if (nwait <= 2 || (res & EXIT_REPARENTING) || (mode != _P_OVERLAY && mode != _P_VFORK)) /* nothing to do */; else if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0) goto reparent; - else if (!(res & EXIT_REPARENTING)) - { - MALLOC_CHECK; - close_all_files (); - MALLOC_CHECK; - } break; case WAIT_OBJECT_0 + 1: sigproc_printf ("signal arrived"); @@ -809,7 +802,6 @@ skip_arg_parsing: { reparent: res |= EXIT_REPARENTING; - close_all_files (); if (!parent_alive) { nwait = 1; @@ -848,33 +840,37 @@ skip_arg_parsing: /* nothing */; else { - int rc; - HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE, - parent->dwProcessId); - sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId); - if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER) + int rc = 0; + HANDLE oldh = myself->hProcess; + HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, + parent->dwProcessId); + sigproc_printf ("parent handle %p, pid %d", h, parent->dwProcessId); + if (h == NULL && GetLastError () == ERROR_INVALID_PARAMETER) rc = 1; - else if (hP) + else if (h) { - ProtectHandle (hP); - rc = DuplicateHandle (hMainProc, pi.hProcess, hP, - &myself->hProcess, 0, FALSE, + ProtectHandle (h); + rc = DuplicateHandle (hMainProc, pi.hProcess, + h, &myself->hProcess, 0, FALSE, DUPLICATE_SAME_ACCESS); - sigproc_printf ("Dup hP %d", rc); - ForceCloseHandle (hP); + sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p", + rc, oldh, myself->hProcess); + ForceCloseHandle (h); } - if (!res) + if (!rc) { - system_printf ("Reparent failed, parent handle %p, %E", hP); + system_printf ("Reparent failed, parent handle %p, %E", h); system_printf ("my dwProcessId %d, myself->dwProcessId %d", GetCurrentProcessId(), myself->dwProcessId); - system_printf ("myself->process_state %x", - myself->process_state); - system_printf ("myself->hProcess %x", myself->hProcess); + system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess); } } - ForceCloseHandle1 (hExeced, childhProc); - hExeced = INVALID_HANDLE_VALUE; + if (hExeced) + { + ForceCloseHandle1 (hExeced, childhProc); + hExeced = INVALID_HANDLE_VALUE; + close_all_files (); + } } else if (exited) {