diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c4bd8f34c..e0f881174 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +Sat Oct 14 01:45:25 2000 Christopher Faylor + + * cygheap.cc (cygheap_fixup_in_child): Don't page round cygheap copied + from parent. + * dcrt0.cc (do_exit): Don't cleanup pinfo on exit. That happens + automatically now. + * exceptions.cc (signal_exit): Ditto. + * fork.cc (fork_parent): Use stack_here value passed in from fork(). + (fork): Figure out top of stack here and pass it to fork_parent. + * pinfo.cc (_pinfo::record_death): Eliminate. + * pinfo.h (_pinfo): Ditto. + * sigproc.cc (proc_exists): Simplify. + (proc_terminate): Ditto. + (remove_zombie): Don't cleanup pinfo stuff. + (wait_sig): Send subproc_ready signal whether execed or spawned. + * spawn.cc (spawn_guts): Always create subproc_ready event. Use it for + both exec and spawn. + (_spawnve): Send proper mode to spawn_guts when mode != _P_OVERLAY. + Thu Oct 12 23:11:05 2000 Christopher Faylor * dtable.cc (dtable::fixup_after_fork): Revert thinko below. diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index ee686fac4..21bde12e1 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -207,9 +207,7 @@ cygheap_fixup_in_child (HANDLE parent, bool execed) /* Copy memory from the parent */ m = 0; - n = (DWORD) pagetrunc (n + 4095); - if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) || - m != n) + if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) || m != n) api_fatal ("Couldn't read parent's cygwin heap %d bytes != %d, %E", n, m); diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 4c8b42879..71775067f 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -973,7 +973,6 @@ enum extern "C" void __stdcall do_exit (int status) { - BOOL cleanup_pinfo; UINT n = (UINT) status; static int NO_COPY exit_state = 0; @@ -1013,10 +1012,7 @@ do_exit (int status) } if (n & EXIT_REPARENTING) - { - n &= ~EXIT_REPARENTING; - cleanup_pinfo = FALSE; - } + n &= ~EXIT_REPARENTING; else { myself->stopsig = 0; @@ -1045,7 +1041,6 @@ do_exit (int status) } tty_terminate (); - cleanup_pinfo = TRUE; } window_terminate (); @@ -1060,11 +1055,6 @@ do_exit (int status) ForceCloseHandle1 (hExeced, childhProc); } - if (cleanup_pinfo) - myself->record_death (); - else - sigproc_printf ("not cleanup_pinfo"); - shared_terminate (); sigproc_printf ("calling ExitProcess %d", n); @@ -1106,7 +1096,6 @@ __api_fatal (const char *fmt, ...) /* We are going down without mercy. Make sure we reset our process_state. */ sigproc_terminate (); - myself->record_death (); #ifdef DEBUGGING (void) try_to_debug (); #endif diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 6f838ee7f..8d8178055 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1005,11 +1005,7 @@ signal_exit (int rc) { rc = EXIT_SIGNAL | (rc << 8); if (exit_already++) - { - /* We are going down - reset our process_state without locking. */ - myself->record_death (); - ExitProcess (rc); - } + ExitProcess (rc); /* We'd like to stop the main thread from executing but when we do that it causes random, inexplicable hangs. So, instead, we set up the priority diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 82047795d..a02e88b0a 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -308,10 +308,9 @@ debug_printf ("hParent %p", hParent); } static int __stdcall -fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch) +fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch) { HANDLE subproc_ready, forker_finished; - void *stack_here = &hParent; DWORD rc; PROCESS_INFORMATION pi = {0, NULL, 0, 0}; static NO_COPY HANDLE last_fork_proc = NULL; @@ -339,8 +338,6 @@ fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - syscall_printf ("CreateProcessA (%s, %s,0,0,1,%x, 0,0,%p,%p)", - myself->progname, myself->progname, c_flags, &si, &pi); if (console_handle != INVALID_HANDLE_VALUE && console_handle != 0) CloseHandle (console_handle); else @@ -407,16 +404,18 @@ fork_parent (HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork ch.cygheap_max = cygheap_max; char sa_buf[1024]; - rc = CreateProcessA (myself->progname, /* image to run */ - myself->progname, /* what we send in arg0 */ - allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, - allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, - TRUE, /* inherit handles from parent */ - c_flags, - NULL, /* environment filled in later */ - 0, /* use current drive/directory */ - &si, - &pi); + syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)", + myself->progname, myself->progname, c_flags, &si, &pi); + rc = CreateProcess (myself->progname, /* image to run */ + myself->progname, /* what we send in arg0 */ + allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, + allow_ntsec ? sec_user (sa_buf) : &sec_none_nih, + TRUE, /* inherit handles from parent */ + c_flags, + NULL, /* environment filled in later */ + 0, /* use current drive/directory */ + &si, + &pi); CloseHandle (hParent); @@ -579,14 +578,11 @@ fork () bool load_dlls; } grouped; - int res; - int x; - MALLOC_CHECK; - // grow_stack_slack (); - debug_printf ("entering"); + grouped.hParent = grouped.first_dll = NULL; + grouped.load_dlls = 0; if (ISSTATE(myself, PID_SPLIT_HEAP)) { @@ -597,13 +593,17 @@ fork () return -1; } - child_info_fork ch; - x = setjmp (ch.jmp); + void *esp; + __asm ("movl %%esp,%0": "=r" (esp)); - if (x != 0) + child_info_fork ch; + + int res = setjmp (ch.jmp); + + if (res) res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls); else - res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, ch); + res = fork_parent (esp, grouped.hParent, grouped.first_dll, grouped.load_dlls, ch); MALLOC_CHECK; syscall_printf ("%d = fork()", res); diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index f14b45c60..68f4923e7 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -174,17 +174,6 @@ _pinfo::copysigs(_pinfo *_other) sigs = _other->sigs; } -void -_pinfo::record_death () -{ - /* CGF FIXME - needed? */ - if (dwProcessId == GetCurrentProcessId () && !my_parent_is_alive ()) - { - process_state = PID_NOT_IN_USE; - hProcess = NULL; - } -} - void pinfo::init (pid_t n, DWORD create, HANDLE in_h) { diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 2c5b862c6..bb1f2fe25 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -119,8 +119,6 @@ private: public: /* Pointer to mmap'ed areas for this process. Set up by fork. */ void *mmap_ptr; - - void record_death (); }; class pinfo diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index a2b01ccde..675feb4f3 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -205,48 +205,8 @@ proc_exists (_pinfo *p) if (p == NULL) return FALSE; - - if (p == myself || p == myself_nowait_nonmain || p == myself_nowait) + else return TRUE; - - if (p->process_state == PID_NOT_IN_USE || !p->dwProcessId) - return FALSE; - - sigproc_printf ("checking for existence of pid %d, window pid %d", p->pid, - p->dwProcessId); - if (p->ppid == myself->pid && p->hProcess != NULL) - { - sigproc_printf ("it's mine, process_state %x", p->process_state); - return proc_can_be_signalled (p); - } - - /* Note: Process is alive if OpenProcess() call fails due to permissions */ - if (((h = OpenProcess (STANDARD_RIGHTS_REQUIRED, FALSE, p->dwProcessId)) - != NULL) || (GetLastError () == ERROR_ACCESS_DENIED)) - { - sigproc_printf ("it exists, %p", h); - if (h) - { - DWORD rc = WaitForSingleObject (h, 0); - CloseHandle (h); - if (rc == WAIT_OBJECT_0) - return 0; - } - return proc_can_be_signalled (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. - */ - if ((p->pid == p->ppid) || (p->ppid == 1) || !pid_exists (p->ppid)) - { - p->hProcess = NULL; - p->process_state = PID_NOT_IN_USE; - } -#endif - return FALSE; } /* Return 1 if this is one of our children, zero otherwise. @@ -500,22 +460,13 @@ proc_terminate (void) else { ForceCloseHandle1 (pchildren[i]->hProcess, childhProc); - if (!proc_exists (pchildren[i])) - { - sigproc_printf ("%d(%d) doesn't exist", pchildren[i]->pid, + sigproc_printf ("%d(%d) closed child handle", pchildren[i]->pid, pchildren[i]->dwProcessId); - pchildren[i]->process_state = PID_NOT_IN_USE; /* a reaped child CGF FIXME -- still needed? */ - } - else - { - sigproc_printf ("%d(%d) closing active child handle", pchildren[i]->pid, - pchildren[i]->dwProcessId); - pchildren[i]->ppid = 1; - if (pchildren[i]->pgid == myself->pid) - pchildren[i]->process_state |= PID_ORPHANED; - } + pchildren[i]->ppid = 1; + if (pchildren[i]->pgid == myself->pid) + pchildren[i]->process_state |= PID_ORPHANED; } - pchildren[i].release (); // FIXME: this breaks older gccs for some reason + pchildren[i].release (); } nchildren = nzombies = 0; @@ -601,6 +552,7 @@ sigproc_init () /* local event signaled when main thread has been dispatched to a signal handler function. */ signal_arrived = CreateEvent(&sec_none_nih, TRUE, FALSE, NULL); + ProtectHandle (signal_arrived); if (!(hwait_sig = makethread (wait_sig, NULL, 0, "sig"))) { @@ -669,14 +621,6 @@ sigproc_terminate (void) WaitForSingleObject (h, 10000); ForceCloseHandle1 (h, hwait_sig); - /* Exiting thread. Cleanup. Don't set to inactive if a child has been - execed with the same pid. */ - if (!myself->dwProcessId || myself->dwProcessId == GetCurrentProcessId ()) - myself->process_state &= ~PID_ACTIVE; - else - sigproc_printf ("Did not clear PID_ACTIVE since %d != %d", - myself->dwProcessId, GetCurrentProcessId ()); - /* In case of a sigsuspend */ SetEvent (signal_arrived); @@ -1052,7 +996,6 @@ remove_zombie (int ci) { 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 (); } @@ -1184,7 +1127,8 @@ wait_sig (VOID *) * windows process waiting to see if it's started a cygwin process or not. * Signalling subproc_ready indicates that we are a cygwin process. */ - if (child_proc_info && child_proc_info->type == PROC_EXEC) + if (child_proc_info && + (child_proc_info->type == PROC_FORK || child_proc_info->type == PROC_SPAWN)) { debug_printf ("subproc_ready %p", child_proc_info->subproc_ready); if (!SetEvent (child_proc_info->subproc_ready)) @@ -1383,6 +1327,7 @@ WFSO (HANDLE hHandle, DWORD dwMilliseconds) DWORD ret; sigframe thisframe (mainthread); ret = WaitForSingleObject (hHandle, dwMilliseconds); +if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds); return ret; } @@ -1394,6 +1339,7 @@ WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds DWORD ret; sigframe thisframe (mainthread); ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds); +if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds); return ret; } } diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index adf5b1f2f..0aab714c1 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -158,21 +158,6 @@ handle (int n, int direction) return fh->get_output_handle (); } -/* Cover function for CreateProcess. - - This function is used by both the routines that search $PATH and those - that do not. This should work out ok as according to the documentation, - CreateProcess only searches $PATH if PROG has no directory elements. - - Spawning doesn't fit well with Posix's fork/exec (one can argue the merits - of either but that's beside the point). If we're exec'ing we want to - record the child pid for fork. If we're spawn'ing we don't want to do - this. It is up to the caller to handle both cases. - - The result is the process id. The handle of the created process is - stored in H. -*/ - HANDLE NO_COPY hExeced = NULL; int @@ -252,7 +237,7 @@ public: int argc; av (int ac, const char * const *av) : calloced (0), argc (ac) { - argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 1) * sizeof (char *)); + argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 5) * sizeof (char *)); memcpy (argv, av, (argc + 1) * sizeof (char *)); } ~av () @@ -348,16 +333,14 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv, si.lpReserved2 = (LPBYTE) &ciresrv; si.cbReserved2 = sizeof (ciresrv); - HANDLE spr = NULL; DWORD chtype; if (mode != _P_OVERLAY && mode != _P_VFORK) chtype = PROC_SPAWN; else - { - spr = CreateEvent(&sec_all, TRUE, FALSE, NULL); - ProtectHandle (spr); - chtype = PROC_EXEC; - } + chtype = PROC_EXEC; + + HANDLE spr = CreateEvent(&sec_all, TRUE, FALSE, NULL); + ProtectHandle (spr); init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr); if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &ciresrv.parent, 0, 1, @@ -555,8 +538,6 @@ skip_arg_parsing: si.hStdError = handle (2, 1); /* Get output handle */ si.cb = sizeof (si); - /* Pass fd table to a child */ - syscall_printf ("spawn_guts (%s, %.132s)", (char *) real_path, one_line.buf); int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED | @@ -696,8 +677,6 @@ skip_arg_parsing: if (mode == _P_OVERLAY) { strcpy (myself->progname, real_path); - // close_all_files (); - proc_terminate (); hExeced = pi.hProcess; myself->dwProcessId = pi.dwProcessId; @@ -765,127 +744,123 @@ skip_arg_parsing: CloseHandle (hToken); DWORD res; + BOOL exited; - if (mode == _P_OVERLAY || mode == _P_VFORK) + HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr}; + int nwait = 3; + + res = 0; + exited = FALSE; + MALLOC_CHECK; + for (int i = 0; i < 100; i++) { - BOOL exited; - - HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr}; - int nwait = 3; - - SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST); - res = 0; - exited = FALSE; - MALLOC_CHECK; - for (int i = 0; i < 100; i++) + switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE)) { - switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - sigproc_printf ("subprocess exited"); - DWORD exitcode; - if (!GetExitCodeProcess (pi.hProcess, &exitcode)) - exitcode = 1; - res |= exitcode; - exited = TRUE; + case WAIT_OBJECT_0: + sigproc_printf ("subprocess exited"); + DWORD exitcode; + if (!GetExitCodeProcess (pi.hProcess, &exitcode)) + exitcode = 1; + res |= exitcode; + exited = TRUE; - 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; - break; - case WAIT_OBJECT_0 + 1: - sigproc_printf ("signal arrived"); - ResetEvent (signal_arrived); - continue; - case WAIT_OBJECT_0 + 2: - if (mode == _P_OVERLAY) + if (nwait > 2 && !(res & EXIT_REPARENTING) && + (mode == _P_OVERLAY || mode == _P_VFORK)) + res |= EXIT_REPARENTING; + break; + case WAIT_OBJECT_0 + 1: + sigproc_printf ("signal arrived"); + ResetEvent (signal_arrived); + continue; + case WAIT_OBJECT_0 + 2: + if (mode == _P_OVERLAY) + { + res |= EXIT_REPARENTING; + if (!parent_alive) { - reparent: - res |= EXIT_REPARENTING; - if (!parent_alive) - { - nwait = 1; - sigproc_terminate (); - continue; - } + nwait = 1; + sigproc_terminate (); + continue; } - break; - case WAIT_FAILED: - DWORD r; - system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E", - nwait, myself->pid, myself->dwProcessId); - system_printf ("waitbuf[0] %p %d", waitbuf[0], - GetHandleInformation (waitbuf[0], &r)); - system_printf ("waitbuf[1] %p = %d", waitbuf[1], - GetHandleInformation (waitbuf[1], &r)); - set_errno (ECHILD); - return -1; } break; + case WAIT_FAILED: + system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E", + nwait, myself->pid, myself->dwProcessId); + system_printf ("waitbuf[0] %p %d", waitbuf[0], + WaitForSingleObject (waitbuf[0], 0)); + system_printf ("waitbuf[1] %p = %d", waitbuf[1], + WaitForSingleObject (waitbuf[1], 0)); + system_printf ("waitbuf[w] %p = %d", waitbuf[2], + WaitForSingleObject (waitbuf[2], 0)); + set_errno (ECHILD); + try_to_debug (); + return -1; } + break; + } - ForceCloseHandle (spr); + ForceCloseHandle (spr); - sigproc_printf ("res = %x", res); + sigproc_printf ("res = %x", res); - if (res & EXIT_REPARENTING) + if (mode == _P_OVERLAY && (res & EXIT_REPARENTING)) + { + /* Try to reparent child process. + * Make handles to child available to parent process and exit with + * EXIT_REPARENTING status. Wait() syscall in parent will then wait + * for newly created child. + */ + pinfo parent (myself->ppid); + if (!parent) + /* nothing */; + else { - /* Try to reparent child process. - * Make handles to child available to parent process and exit with - * EXIT_REPARENTING status. Wait() syscall in parent will then wait - * for newly created child. - */ - pinfo parent (myself->ppid); - if (!parent) - /* nothing */; - else + 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 (h) { - 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 (h) - { - ProtectHandle (h); - rc = DuplicateHandle (hMainProc, pi.hProcess, - h, &myself->hProcess, 0, FALSE, - DUPLICATE_SAME_ACCESS); - sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p", - rc, oldh, myself->hProcess); - ForceCloseHandle (h); - } - if (!rc) - { - system_printf ("Reparent failed, parent handle %p, %E", h); - system_printf ("my dwProcessId %d, myself->dwProcessId %d", - GetCurrentProcessId(), myself->dwProcessId); - system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess); - } + ProtectHandle (h); + rc = DuplicateHandle (hMainProc, pi.hProcess, + h, &myself->hProcess, 0, FALSE, + DUPLICATE_SAME_ACCESS); + sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p", + rc, oldh, myself->hProcess); + ForceCloseHandle (h); } - if (hExeced) + if (!rc) { - ForceCloseHandle1 (hExeced, childhProc); - hExeced = INVALID_HANDLE_VALUE; - close_all_files (); + system_printf ("Reparent failed, parent handle %p, %E", h); + system_printf ("my dwProcessId %d, myself->dwProcessId %d", + GetCurrentProcessId(), myself->dwProcessId); + system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess); } } - else if (exited) + if (hExeced) { ForceCloseHandle1 (hExeced, childhProc); - hExeced = INVALID_HANDLE_VALUE; // stop do_exit from attempting to terminate child + hExeced = INVALID_HANDLE_VALUE; } - - MALLOC_CHECK; - if (mode == _P_OVERLAY) - ExitProcess (res); } + else if (exited) + { + ForceCloseHandle1 (hExeced, childhProc); + hExeced = INVALID_HANDLE_VALUE; // stop do_exit from attempting to terminate child + } + + MALLOC_CHECK; switch (mode) { + case _P_OVERLAY: + proc_terminate (); + ExitProcess (0); + break; case _P_WAIT: waitpid (cygpid, (int *) &res, 0); break; @@ -945,7 +920,7 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv, case _P_WAIT: case _P_DETACH: subproc_init (); - ret = spawn_guts (hToken, path, argv, envp, 0); + ret = spawn_guts (hToken, path, argv, envp, mode); if (vf && ret > 0) { vf->pid = ret;