mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 21:09:22 +08:00
* 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.
This commit is contained in:
parent
cbe4c8e234
commit
aece55b982
@ -1,3 +1,22 @@
|
||||
Sat Oct 14 01:45:25 2000 Christopher Faylor <cgf@cygnus.com>
|
||||
|
||||
* 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 <cgf@cygnus.com>
|
||||
|
||||
* dtable.cc (dtable::fixup_after_fork): Revert thinko below.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -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,7 +404,9 @@ 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 */
|
||||
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,
|
||||
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
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,
|
||||
sigproc_printf ("%d(%d) closed 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].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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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,15 +744,11 @@ skip_arg_parsing:
|
||||
CloseHandle (hToken);
|
||||
|
||||
DWORD res;
|
||||
|
||||
if (mode == _P_OVERLAY || mode == _P_VFORK)
|
||||
{
|
||||
BOOL exited;
|
||||
|
||||
HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
|
||||
int nwait = 3;
|
||||
|
||||
SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
|
||||
res = 0;
|
||||
exited = FALSE;
|
||||
MALLOC_CHECK;
|
||||
@ -789,10 +764,9 @@ skip_arg_parsing:
|
||||
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;
|
||||
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");
|
||||
@ -801,7 +775,6 @@ skip_arg_parsing:
|
||||
case WAIT_OBJECT_0 + 2:
|
||||
if (mode == _P_OVERLAY)
|
||||
{
|
||||
reparent:
|
||||
res |= EXIT_REPARENTING;
|
||||
if (!parent_alive)
|
||||
{
|
||||
@ -812,14 +785,16 @@ skip_arg_parsing:
|
||||
}
|
||||
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));
|
||||
WaitForSingleObject (waitbuf[0], 0));
|
||||
system_printf ("waitbuf[1] %p = %d", waitbuf[1],
|
||||
GetHandleInformation (waitbuf[1], &r));
|
||||
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;
|
||||
@ -829,7 +804,7 @@ skip_arg_parsing:
|
||||
|
||||
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
|
||||
@ -870,7 +845,6 @@ skip_arg_parsing:
|
||||
{
|
||||
ForceCloseHandle1 (hExeced, childhProc);
|
||||
hExeced = INVALID_HANDLE_VALUE;
|
||||
close_all_files ();
|
||||
}
|
||||
}
|
||||
else if (exited)
|
||||
@ -880,12 +854,13 @@ skip_arg_parsing:
|
||||
}
|
||||
|
||||
MALLOC_CHECK;
|
||||
if (mode == _P_OVERLAY)
|
||||
ExitProcess (res);
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user