Throughout use "have_execed" macro rather than "hExeced" global handle.

Throughout rename _PROC_* to _CH_*.
* child_info.h: Include "pinfo.h".
(child_info_types): Rename _PROC_* -> _CH_* to avoid confusion with similarly
named constants.
(_PROC_*): Delete unneeded aliases.
(PROC_*): Ditto.
(CURR_CHILD_INFO_MAGIC): Ditto.
(cchildren): Define using "pinfo_minimal".
(child_info::set_saw_ctrl_c): Move to
(child_info_spawn::set_saw_ctrl_c): Here.
(child_info_spawn::lock): New field.
(child_info_spawn::hExeced): Ditto.
(child_info_spawn::ev): Ditto.
(child_info_spawn::~child_info_spawn): Move to sigproc.cc.
(child_info_spawn::child_info_spawn): Ditto.
(child_info_spawn::cleanup): Declare new function.
(child_info_spawn::set_saw_ctrl_c): Move to this class.  Set flag only when
execed and return true when we have set the flag.
(child_info_spawn::child_info_spawn::signal_myself_exited): New function.
(child_info_spawn::wait_for_myself): Ditto.
(child_info_spawn::has_execed_cygwin): Ditto.
(child_info_spawn::has_execed): Ditto.  Replaces "hExeced" test.
(child_info_spawn::operator HANDLE&): New operator.
(child_info_spawn::worker): Define old "spawn_guts" as class member.
(ch_spawn): Declare.
(have_execed): Define.
(have_execed_cygwin): Ditto.
* cygheap.h: Update comment.
* dcrt0.cc (get_cygwin_startup_info): Use _CH_* enums.
(child_info_spawn::handle_spawn): Ditto.
(dll_crt0_0): Ditto.
(multiple_cygwin_problem): Ditto.
* exceptions.cc (chExeced): Delete obsolete declaration.
(ctrl_c_handler): Reference set_saw_ctrl_c via new ch_spawn global.
* globals.cc (hExeced): Delete.
* pinfo.cc (pinfo::thisproc): Refer to cygheap as ::cygheap for consistency in
handle naming when -DDEBUGGING.
(pinfo::init): Accommodate case where myself.h is known but h0 is passed in.
(pinfo::pinfo): New constructor for setting up a pinfo passed in by previous
exec'or.
(pinfo::proc_waiter): Don't handle subprocess if we're in the process of
exiting due to an exec of a cygwin process.  Don't close rd_proc_pipe here.
Close it when we actually are finished with the process.  Use new
ch_spawn.signal_myself_exited function to let exec stub know that subprocess
has exited.
(pinfo::wait): Clarify debugging output.
(pinfo::release): Use "close_h" to close all handles to avoid races.
(winpids::add): Assume that elements of the array do not need to be zeroed and
are properly initialized or suffer problems on pinfo::release.  Don't close
hProcess since release does that now.
* pinfo.h: Update comment.
(pinfo_minimal): Move some elements from pinfo here so that child_info_spawn
can use them.
(pinfo): Inherit from pinfo_minimal.
(pinfo::pinfo): Modify to accommodate new pinfo_minimal.
(pinfo::allow_remove): New function.
* sigproc.cc (proc_subproc): Use boolean values for true/false.  Implement
PROC_EXEC_CLEANUP.
(proc_terminate): Set ppid = 1 since the procs list will only be iterated when
the process has not execed.  Don't do any cleanup here since it is now handled
in pinfo::release.
(sigproc_init): Initialize sync_proc_subproc earlier.
(child_info::child_info): Assume that all important fields are properly
initialized and avoid memset().
(child_info_spawn::child_info_spawn): Specifically test for execing and then
set up appropriate fields in the struct.
(child_info_spawn::cleanup): Define new function.
(child_info_spawn::record_children): Specifically test for being execed here.
Fill in pinfo_minimal part of children array.
(child_info_spawn::reattach_children): Use constructor to duplicate information
for previous exec'or.  Add more debugging output.
(remove_proc): Force deletion of thread when exiting due to exec.  Rely on
pinfo::cleanup in release.
* sigproc.h (PROC_EXEC_CLEANUP): New enum.
(PROC_DETACHED_CHILD): Delete.
* spawn.cc (chExeced): Delete.
(child_info_spawn::worker): Rename from spawn_guts.  Use elements of
child_info_spawn throughout rather than ch.whatever.  Use ::cygheap to refer to
global rather than element of child_info.  Use wait_for_myself() rather than
waitpid().  Call child_info_spawn::cleanup on function return.
(spawnve): Reflect movement of spawn_guts functionality into
child_info_spawn::worker.
* syscalls.cc (popen): Ditto.
* winsup.h (spawn_guts): Delete declaration.
This commit is contained in:
Christopher Faylor 2011-11-14 01:29:49 +00:00
parent 46e7439b9d
commit 56a1971526
27 changed files with 458 additions and 242 deletions

View File

@ -1,3 +1,93 @@
2011-11-10 Christopher Faylor <me.cygwin2011@cgf.cx>
Throughout use "have_execed" macro rather than "hExeced" global handle.
Throughout rename _PROC_* to _CH_*.
* child_info.h: Include "pinfo.h".
(child_info_types): Rename _PROC_* -> _CH_* to avoid confusion with
similarly named constants.
(_PROC_*): Delete unneeded aliases.
(PROC_*): Ditto.
(CURR_CHILD_INFO_MAGIC): Ditto.
(cchildren): Define using "pinfo_minimal".
(child_info::set_saw_ctrl_c): Move to
(child_info_spawn::set_saw_ctrl_c): Here.
(child_info_spawn::lock): New field.
(child_info_spawn::hExeced): Ditto.
(child_info_spawn::ev): Ditto.
(child_info_spawn::~child_info_spawn): Move to sigproc.cc.
(child_info_spawn::child_info_spawn): Ditto.
(child_info_spawn::cleanup): Declare new function.
(child_info_spawn::set_saw_ctrl_c): Move to this class. Set flag only
when execed and return true when we have set the flag.
(child_info_spawn::child_info_spawn::signal_myself_exited): New function.
(child_info_spawn::wait_for_myself): Ditto.
(child_info_spawn::has_execed_cygwin): Ditto.
(child_info_spawn::has_execed): Ditto. Replaces "hExeced" test.
(child_info_spawn::operator HANDLE&): New operator.
(child_info_spawn::worker): Define old "spawn_guts" as class member.
(ch_spawn): Declare.
(have_execed): Define.
(have_execed_cygwin): Ditto.
* cygheap.h: Update comment.
* dcrt0.cc (get_cygwin_startup_info): Use _CH_* enums.
(child_info_spawn::handle_spawn): Ditto.
(dll_crt0_0): Ditto.
(multiple_cygwin_problem): Ditto.
* exceptions.cc (chExeced): Delete obsolete declaration.
(ctrl_c_handler): Reference set_saw_ctrl_c via new ch_spawn global.
* globals.cc (hExeced): Delete.
* pinfo.cc (pinfo::thisproc): Refer to cygheap as ::cygheap for
consistency in handle naming when -DDEBUGGING.
(pinfo::init): Accommodate case where myself.h is known but h0 is
passed in.
(pinfo::pinfo): New constructor for setting up a pinfo passed in by
previous exec'or.
(pinfo::proc_waiter): Don't handle subprocess if we're in the process
of exiting due to an exec of a cygwin process. Don't close
rd_proc_pipe here. Close it when we actually are finished with the
process. Use new ch_spawn.signal_myself_exited function to let exec
stub know that subprocess has exited.
(pinfo::wait): Clarify debugging output.
(pinfo::release): Use "close_h" to close all handles to avoid races.
(winpids::add): Assume that elements of the array do not need to be
zeroed and are properly initialized or suffer problems on
pinfo::release. Don't close hProcess since release does that now.
* pinfo.h: Update comment.
(pinfo_minimal): Move some elements from pinfo here so that
child_info_spawn can use them.
(pinfo): Inherit from pinfo_minimal.
(pinfo::pinfo): Modify to accommodate new pinfo_minimal.
(pinfo::allow_remove): New function.
* sigproc.cc (proc_subproc): Use boolean values for true/false.
Implement PROC_EXEC_CLEANUP.
(proc_terminate): Set ppid = 1 since the procs list will only be
iterated when the process has not execed. Don't do any cleanup here
since it is now handled in pinfo::release.
(sigproc_init): Initialize sync_proc_subproc earlier.
(child_info::child_info): Assume that all important fields are properly
initialized and avoid memset().
(child_info_spawn::child_info_spawn): Specifically test for execing and
then set up appropriate fields in the struct.
(child_info_spawn::cleanup): Define new function.
(child_info_spawn::record_children): Specifically test for being execed
here. Fill in pinfo_minimal part of children array.
(child_info_spawn::reattach_children): Use constructor to duplicate
information for previous exec'or. Add more debugging output.
(remove_proc): Force deletion of thread when exiting due to exec. Rely
on pinfo::cleanup in release.
* sigproc.h (PROC_EXEC_CLEANUP): New enum.
(PROC_DETACHED_CHILD): Delete.
* spawn.cc (chExeced): Delete.
(child_info_spawn::worker): Rename from spawn_guts. Use elements of
child_info_spawn throughout rather than ch.whatever. Use ::cygheap to
refer to global rather than element of child_info. Use
wait_for_myself() rather than waitpid(). Call
child_info_spawn::cleanup on function return.
(spawnve): Reflect movement of spawn_guts functionality into
child_info_spawn::worker.
* syscalls.cc (popen): Ditto.
* winsup.h (spawn_guts): Delete declaration.
2011-11-08 Corinna Vinschen <corinna@vinschen.de> 2011-11-08 Corinna Vinschen <corinna@vinschen.de>
* posix.sgml (std-gnu): Add ptsname_r. * posix.sgml (std-gnu): Add ptsname_r.

View File

@ -51,6 +51,9 @@ __assert_func (const char *file, int line, const char *func,
small_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s\n", small_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line, failedexpr, file, line,
func ? ", function: " : "", func ? func : ""); func ? ", function: " : "", func ? func : "");
debug_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s",
failedexpr, file, line,
func ? ", function: " : "", func ? func : "");
} }
#ifdef DEBUGGING #ifdef DEBUGGING

View File

@ -13,10 +13,11 @@ details. */
enum child_info_types enum child_info_types
{ {
_PROC_EXEC, _CH_NADA = 0,
_PROC_SPAWN, _CH_EXEC = 1,
_PROC_FORK, _CH_SPAWN = 2,
_PROC_WHOOPS _CH_FORK = 3,
_CH_WHOOPS = 4
}; };
enum child_status enum child_status
@ -31,21 +32,18 @@ enum child_status
#define PROC_MAGIC_GENERIC 0xaf00fa00 #define PROC_MAGIC_GENERIC 0xaf00fa00
#define PROC_EXEC (_PROC_EXEC)
#define PROC_SPAWN (_PROC_SPAWN)
#define PROC_FORK (_PROC_FORK)
#define EXEC_MAGIC_SIZE sizeof(child_info) #define EXEC_MAGIC_SIZE sizeof(child_info)
/* Change this value if you get a message indicating that it is out-of-sync. */ /* Change this value if you get a message indicating that it is out-of-sync. */
#define CURR_CHILD_INFO_MAGIC 0xa049a83aU #define CURR_CHILD_INFO_MAGIC 0x941e0a4aU
#define NPROCS 256 #define NPROCS 256
#include "pinfo.h"
struct cchildren struct cchildren
{ {
pid_t pid; pid_t pid;
HANDLE rd_proc_pipe; pinfo_minimal p;
}; };
/* NOTE: Do not make gratuitous changes to the names or organization of the /* NOTE: Do not make gratuitous changes to the names or organization of the
@ -80,7 +78,6 @@ public:
bool isstraced () const {return !!(flag & _CI_STRACED);} bool isstraced () const {return !!(flag & _CI_STRACED);}
bool iscygwin () const {return !!(flag & _CI_ISCYGWIN);} bool iscygwin () const {return !!(flag & _CI_ISCYGWIN);}
bool saw_ctrl_c () const {return !!(flag & _CI_SAW_CTRL_C);} bool saw_ctrl_c () const {return !!(flag & _CI_SAW_CTRL_C);}
void set_saw_ctrl_c () {flag |= _CI_SAW_CTRL_C;}
}; };
class mount_info; class mount_info;
@ -118,6 +115,9 @@ public:
class child_info_spawn: public child_info class child_info_spawn: public child_info
{ {
muto *lock;
HANDLE hExeced;
HANDLE ev;
public: public:
cygheap_exec_info *moreinfo; cygheap_exec_info *moreinfo;
int __stdin; int __stdin;
@ -126,30 +126,53 @@ public:
int nchildren; int nchildren;
cchildren children[NPROCS]; cchildren children[NPROCS];
~child_info_spawn () void cleanup ();
{ child_info_spawn () {};
if (moreinfo)
{
if (moreinfo->envp)
{
for (char **e = moreinfo->envp; *e; e++)
cfree (*e);
cfree (moreinfo->envp);
}
if (type != _PROC_SPAWN && moreinfo->myself_pinfo)
CloseHandle (moreinfo->myself_pinfo);
cfree (moreinfo);
}
}
child_info_spawn (): moreinfo (NULL), nchildren (0) {};
child_info_spawn (child_info_types, bool); child_info_spawn (child_info_types, bool);
void record_children (); void record_children ();
void reattach_children (); void reattach_children ();
void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;} void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;}
void set (child_info_types ci, bool b) { new (this) child_info_spawn (ci, b);} void set (child_info_types ci, bool b) { new (this) child_info_spawn (ci, b);}
void handle_spawn () __attribute__ ((regparm (1))); void handle_spawn () __attribute__ ((regparm (1)));
bool set_saw_ctrl_c ()
{
if (!has_execed ())
return false;
flag |= _CI_SAW_CTRL_C;
return true;
}
bool signal_myself_exited ()
{
if (!ev)
return false;
else
{
SetEvent (ev);
return true;
}
}
void wait_for_myself () { WaitForSingleObject (ev, INFINITE); }
bool has_execed () const
{
if (hExeced)
return true;
if (type != _CH_EXEC)
return false;
lock->acquire ();
lock->release ();
return !!hExeced;
}
bool has_execed_cygwin () const { return iscygwin () && has_execed (); }
operator HANDLE& () {return hExeced;}
int worker (const char *, const char *const *, const char *const [], int,
int = -1, int = -1) __attribute__ ((regparm (3)));;
}; };
extern child_info_spawn ch_spawn;
#define have_execed ch_spawn.has_execed ()
#define have_execed_cygwin ch_spawn.has_execed_cygwin ()
void __stdcall init_child_info (DWORD, child_info *, HANDLE); void __stdcall init_child_info (DWORD, child_info *, HANDLE);
extern "C" { extern "C" {

View File

@ -64,8 +64,11 @@ cygheap_fixup_in_child (bool execed)
cygheap_max = cygheap = (init_cygheap *) _cygheap_start; cygheap_max = cygheap = (init_cygheap *) _cygheap_start;
_csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap); _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL); child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL);
debug_printf ("HERE");
cygheap_init (); cygheap_init ();
debug_printf ("HERE 2");
debug_fixup_after_fork_exec (); debug_fixup_after_fork_exec ();
debug_printf ("HERE 2, %d", execed);
if (execed) if (execed)
{ {
cygheap->hooks.next = NULL; cygheap->hooks.next = NULL;
@ -83,6 +86,7 @@ cygheap_fixup_in_child (bool execed)
_cfree (ce); /* Marked by parent for freeing in child */ _cfree (ce); /* Marked by parent for freeing in child */
} }
} }
debug_printf ("HERE 3, %d", execed);
} }
int int

View File

@ -215,8 +215,8 @@ private:
int error; /* This contains an errno number which corresponds int error; /* This contains an errno number which corresponds
to the problem with this path when trying to start to the problem with this path when trying to start
a native Win32 application. See cwdstuff::set for a native Win32 application. See cwdstuff::set for
how it gets set. See spawn_guts for how it's how it gets set. See child_info_spawn::worker for how
evaluated. */ it's evaluated. */
void override_win32_cwd (bool, ULONG); void override_win32_cwd (bool, ULONG);
public: public:

View File

@ -197,7 +197,7 @@ _cygtls::find_tls (int sig)
{ {
static int NO_COPY threadlist_ix; static int NO_COPY threadlist_ix;
debug_printf ("sig %d\n", sig); debug_printf ("signal %d\n", sig);
sentry here (INFINITE); sentry here (INFINITE);
_cygtls *res = NULL; _cygtls *res = NULL;

View File

@ -532,12 +532,12 @@ get_cygwin_startup_info ()
unsigned should_be_cb = 0; unsigned should_be_cb = 0;
switch (res->type) switch (res->type)
{ {
case _PROC_FORK: case _CH_FORK:
in_forkee = true; in_forkee = true;
should_be_cb = sizeof (child_info_fork); should_be_cb = sizeof (child_info_fork);
/* fall through */; /* fall through */;
case _PROC_SPAWN: case _CH_SPAWN:
case _PROC_EXEC: case _CH_EXEC:
if (!should_be_cb) if (!should_be_cb)
should_be_cb = sizeof (child_info_spawn); should_be_cb = sizeof (child_info_spawn);
if (should_be_cb != res->cb) if (should_be_cb != res->cb)
@ -546,7 +546,6 @@ get_cygwin_startup_info ()
multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union)); multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
if (res->isstraced ()) if (res->isstraced ())
{ {
res->ready (false);
for (unsigned i = 0; !being_debugged () && i < 10000; i++) for (unsigned i = 0; !being_debugged () && i < 10000; i++)
yield (); yield ();
strace.hello (); strace.hello ();
@ -555,7 +554,7 @@ get_cygwin_startup_info ()
default: default:
system_printf ("unknown exec type %d", res->type); system_printf ("unknown exec type %d", res->type);
/* intentionally fall through */ /* intentionally fall through */
case _PROC_WHOOPS: case _CH_WHOOPS:
res = NULL; res = NULL;
break; break;
} }
@ -628,7 +627,7 @@ child_info_spawn::handle_spawn ()
/* If we're execing we may have "inherited" a list of children forked by the /* If we're execing we may have "inherited" a list of children forked by the
previous process executing under this pid. Reattach them here so that we previous process executing under this pid. Reattach them here so that we
can wait for them. */ can wait for them. */
if (type == _PROC_EXEC) if (type == _CH_EXEC)
reattach_children (); reattach_children ();
ready (true); ready (true);
@ -692,11 +691,11 @@ dll_crt0_0 ()
cygwin_user_h = child_proc_info->user_h; cygwin_user_h = child_proc_info->user_h;
switch (child_proc_info->type) switch (child_proc_info->type)
{ {
case _PROC_FORK: case _CH_FORK:
fork_info->handle_fork (); fork_info->handle_fork ();
break; break;
case _PROC_SPAWN: case _CH_SPAWN:
case _PROC_EXEC: case _CH_EXEC:
spawn_info->handle_spawn (); spawn_info->handle_spawn ();
break; break;
} }
@ -1121,7 +1120,7 @@ multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned vers
{ {
if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap"))) if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
{ {
child_proc_info->type = _PROC_WHOOPS; child_proc_info->type = _CH_WHOOPS;
return; return;
} }

View File

@ -171,6 +171,7 @@ delete_handle (handle_list *hl)
void void
debug_fixup_after_fork_exec () debug_fixup_after_fork_exec ()
{ {
debug_printf ("BEFORE");
/* No lock needed at this point */ /* No lock needed at this point */
handle_list *hl; handle_list *hl;
for (hl = &cygheap->debug.starth; hl->next != NULL; /* nothing */) for (hl = &cygheap->debug.starth; hl->next != NULL; /* nothing */)
@ -178,6 +179,7 @@ debug_fixup_after_fork_exec ()
hl = hl->next; hl = hl->next;
else else
delete_handle (hl); // removes hl->next delete_handle (hl); // removes hl->next
debug_printf ("AFTER");
} }
static bool __stdcall static bool __stdcall

View File

@ -41,8 +41,6 @@ extern "C" {
extern void sigdelayed (); extern void sigdelayed ();
}; };
extern child_info_spawn *chExeced;
static BOOL WINAPI ctrl_c_handler (DWORD); static BOOL WINAPI ctrl_c_handler (DWORD);
/* This is set to indicate that we have already exited. */ /* This is set to indicate that we have already exited. */
@ -603,7 +601,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
} }
debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp); debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip); debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo)); bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
if (masked) if (masked)
@ -822,7 +820,7 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga)
/* Clear any waiting threads prior to dispatching to handler function */ /* Clear any waiting threads prior to dispatching to handler function */
int res = SetEvent (signal_arrived); // For an EINTR case int res = SetEvent (signal_arrived); // For an EINTR case
proc_subproc (PROC_CLEARWAIT, 1); proc_subproc (PROC_CLEARWAIT, 1);
sigproc_printf ("armed signal_arrived %p, sig %d, res %d", signal_arrived, sigproc_printf ("armed signal_arrived %p, signal %d, res %d", signal_arrived,
sig, res); sig, res);
} }
@ -844,7 +842,7 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
if (tls->sig) if (tls->sig)
{ {
sigproc_printf ("trying to send sig %d but signal %d already armed", sigproc_printf ("trying to send signal %d but signal %d already armed",
sig, tls->sig); sig, tls->sig);
goto out; goto out;
} }
@ -988,11 +986,8 @@ ctrl_c_handler (DWORD type)
} }
} }
if (chExeced) if (ch_spawn.set_saw_ctrl_c ())
{ return TRUE;
chExeced->set_saw_ctrl_c ();
return TRUE;
}
/* We're only the process group leader when we have a valid pinfo structure. /* We're only the process group leader when we have a valid pinfo structure.
If we don't have one, then the parent "stub" will handle the signal. */ If we don't have one, then the parent "stub" will handle the signal. */
@ -1193,7 +1188,7 @@ sigpacket::process ()
bool masked; bool masked;
void *handler; void *handler;
if (!hExeced || (void *) thissig.sa_handler == (void *) SIG_IGN) if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN)
handler = (void *) thissig.sa_handler; handler = (void *) thissig.sa_handler;
else if (tls) else if (tls)
return 1; return 1;
@ -1332,10 +1327,10 @@ exit_sig:
void void
_cygtls::signal_exit (int rc) _cygtls::signal_exit (int rc)
{ {
if (hExeced) if (have_execed)
{ {
sigproc_printf ("terminating captive process"); sigproc_printf ("terminating captive process");
TerminateProcess (hExeced, sigExeced = rc); TerminateProcess (ch_spawn, sigExeced = rc);
} }
signal_debugger (rc & 0x7f); signal_debugger (rc & 0x7f);
@ -1343,7 +1338,7 @@ _cygtls::signal_exit (int rc)
stackdump (thread_context.ebp, 1, 1); stackdump (thread_context.ebp, 1, 1);
lock_process until_exit (true); lock_process until_exit (true);
if (hExeced || exit_state > ES_PROCESS_LOCKED) if (have_execed || exit_state > ES_PROCESS_LOCKED)
myself.exit (rc); myself.exit (rc);
/* Starve other threads in a vain attempt to stop them from doing something /* Starve other threads in a vain attempt to stop them from doing something

View File

@ -17,6 +17,10 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "sync.h"
#include "dtable.h"
#include "cygheap.h"
#include "child_info.h"
/* /*
* Robert Collins: * Robert Collins:
@ -263,7 +267,7 @@ fhandler_dev_clipboard::lseek (_off64_t offset, int whence)
int int
fhandler_dev_clipboard::close () fhandler_dev_clipboard::close ()
{ {
if (!hExeced) if (!have_execed)
{ {
eof = true; eof = true;
pos = 0; pos = 0;

View File

@ -33,6 +33,8 @@ details. */
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include "registry.h" #include "registry.h"
#include <asm/socket.h> #include <asm/socket.h>
#include "sync.h"
#include "child_info.h"
/* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer /* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer
is allocated using tmp_pathbuf!!! */ is allocated using tmp_pathbuf!!! */
@ -840,7 +842,7 @@ fhandler_console::close ()
{ {
CloseHandle (get_io_handle ()); CloseHandle (get_io_handle ());
CloseHandle (get_output_handle ()); CloseHandle (get_output_handle ());
if (!hExeced) if (!have_execed)
cygheap->manage_console_count ("fhandler_console::close", -1); cygheap->manage_console_count ("fhandler_console::close", -1);
return 0; return 0;
} }

View File

@ -15,6 +15,10 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "sync.h"
#include "dtable.h"
#include "cygheap.h"
#include "child_info.h"
#define RANDOM 8 #define RANDOM 8
#define URANDOM 9 #define URANDOM 9
@ -170,7 +174,7 @@ fhandler_dev_random::lseek (_off64_t off, int whence)
int int
fhandler_dev_random::close () fhandler_dev_random::close ()
{ {
if (!hExeced && crypt_prov) if (!have_execed && crypt_prov)
while (!CryptReleaseContext (crypt_prov, 0) while (!CryptReleaseContext (crypt_prov, 0)
&& GetLastError () == ERROR_BUSY) && GetLastError () == ERROR_BUSY)
Sleep (10); Sleep (10);

View File

@ -19,6 +19,7 @@ details. */
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info.h"
#define _COMPILING_NEWLIB #define _COMPILING_NEWLIB
#include <dirent.h> #include <dirent.h>
@ -851,7 +852,7 @@ fhandler_registry::close ()
res = -1; res = -1;
} }
} }
if (!hExeced && value_name) if (!have_execed && value_name)
{ {
cfree (value_name); cfree (value_name);
value_name = NULL; value_name = NULL;

View File

@ -23,6 +23,7 @@ details. */
#include "cygheap.h" #include "cygheap.h"
#include "shared_info.h" #include "shared_info.h"
#include "sigproc.h" #include "sigproc.h"
#include "child_info.h"
/* Media changes and bus resets are sometimes reported and the function /* Media changes and bus resets are sometimes reported and the function
hasn't been executed. We repeat all functions which return with one hasn't been executed. We repeat all functions which return with one
@ -1236,7 +1237,7 @@ fhandler_dev_tape::close ()
int ret = 0; int ret = 0;
int cret = 0; int cret = 0;
if (!hExeced) if (!have_execed)
{ {
lock (-1); lock (-1);
ret = mt.drive (driveno ())->close (get_handle (), is_rewind_device ()); ret = mt.drive (driveno ())->close (get_handle (), is_rewind_device ());

View File

@ -547,11 +547,11 @@ fhandler_pty_slave::open_setup (int flags)
void void
fhandler_pty_slave::cleanup () fhandler_pty_slave::cleanup ()
{ {
/* This used to always call fhandler_pty_common::close when hExeced but that /* This used to always call fhandler_pty_common::close when we were execing
caused multiple closes of the handles associated with this pty. Since but that caused multiple closes of the handles associated with this pty.
close_all_files is not called until after the cygwin process has synced Since close_all_files is not called until after the cygwin process has
or before a non-cygwin process has exited, it should be safe to just synced or before a non-cygwin process has exited, it should be safe to
close this normally. cgf 2006-05-20 */ just close this normally. cgf 2006-05-20 */
cygheap->manage_console_count ("fhandler_pty_slave::close", -1); cygheap->manage_console_count ("fhandler_pty_slave::close", -1);
report_tty_counts (this, "closed", ""); report_tty_counts (this, "closed", "");
} }
@ -1286,8 +1286,8 @@ fhandler_pty_master::close ()
fhandler_pty_common::close (); fhandler_pty_common::close ();
if (hExeced || get_ttyp ()->master_pid != myself->pid) if (have_execed || get_ttyp ()->master_pid != myself->pid)
termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid); termios_printf ("not clearing: %d, master_pid %d", have_execed, get_ttyp ()->master_pid);
else else
get_ttyp ()->set_master_closed (); get_ttyp ()->set_master_closed ();

View File

@ -16,6 +16,8 @@ details. */
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sync.h"
#include "child_info.h"
#include <dirent.h> #include <dirent.h>
@ -168,7 +170,7 @@ fhandler_virtual::dup (fhandler_base * child, int flags)
int int
fhandler_virtual::close () fhandler_virtual::close ()
{ {
if (!hExeced) if (!have_execed)
{ {
if (filebuf) if (filebuf)
{ {

View File

@ -419,7 +419,9 @@ frok::parent (volatile char * volatile stack_here)
&si, &si,
&pi); &pi);
if (!rc) if (rc)
debug_printf ("forked pid %u", pi.dwProcessId);
else
{ {
this_errno = geterrno_from_win_error (); this_errno = geterrno_from_win_error ();
error ("CreateProcessW failed for '%W'", myself->progname); error ("CreateProcessW failed for '%W'", myself->progname);

View File

@ -22,7 +22,6 @@ HANDLE NO_COPY hMainThread;
HANDLE NO_COPY hProcToken; HANDLE NO_COPY hProcToken;
HANDLE NO_COPY hProcImpToken; HANDLE NO_COPY hProcImpToken;
HMODULE NO_COPY cygwin_hmodule; HMODULE NO_COPY cygwin_hmodule;
HANDLE NO_COPY hExeced;
int NO_COPY sigExeced; int NO_COPY sigExeced;
WCHAR NO_COPY windows_system_directory[MAX_PATH]; WCHAR NO_COPY windows_system_directory[MAX_PATH];
UINT NO_COPY windows_system_directory_length; UINT NO_COPY windows_system_directory_length;

View File

@ -77,10 +77,10 @@ pinfo::thisproc (HANDLE h)
else if (!child_proc_info) /* child_proc_info is only set when this process else if (!child_proc_info) /* child_proc_info is only set when this process
was started by another cygwin process */ was started by another cygwin process */
procinfo->start_time = time (NULL); /* Register our starting time. */ procinfo->start_time = time (NULL); /* Register our starting time. */
else if (cygheap->pid_handle) else if (::cygheap->pid_handle)
{ {
ForceCloseHandle (cygheap->pid_handle); ForceCloseHandle (::cygheap->pid_handle);
cygheap->pid_handle = NULL; ::cygheap->pid_handle = NULL;
} }
} }
@ -215,6 +215,24 @@ pinfo::exit (DWORD n)
} }
# undef self # undef self
inline void
pinfo::_pinfo_release ()
{
if (procinfo)
{
void *unmap_procinfo = procinfo;
procinfo = NULL;
UnmapViewOfFile (unmap_procinfo);
}
HANDLE close_h;
if (h)
{
close_h = h;
h = NULL;
ForceCloseHandle1 (close_h, pinfo_shared_handle);
}
}
void void
pinfo::init (pid_t n, DWORD flag, HANDLE h0) pinfo::init (pid_t n, DWORD flag, HANDLE h0)
{ {
@ -233,7 +251,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
DWORD access = FILE_MAP_READ DWORD access = FILE_MAP_READ
| (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW) | (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW)
? FILE_MAP_WRITE : 0); ? FILE_MAP_WRITE : 0);
if (!h0) if (!h0 || myself.h)
shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN; shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN;
else else
{ {
@ -331,7 +349,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
break; break;
loop: loop:
release (); _pinfo_release ();
if (h0) if (h0)
yield (); yield ();
} }
@ -344,7 +362,7 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
else else
{ {
h = h0; h = h0;
release (); _pinfo_release ();
} }
} }
@ -365,6 +383,35 @@ pinfo::set_acl()
debug_printf ("NtSetSecurityObject %p", status); debug_printf ("NtSetSecurityObject %p", status);
} }
pinfo::pinfo (HANDLE parent, pinfo_minimal& from, pid_t pid):
pinfo_minimal (), destroy (false), procinfo (NULL), waiter_ready (false),
wait_thread (NULL)
{
HANDLE herr;
const char *duperr = NULL;
if (!DuplicateHandle (parent, herr = from.rd_proc_pipe, GetCurrentProcess (),
&rd_proc_pipe, 0, false, DUPLICATE_SAME_ACCESS))
duperr = "couldn't duplicate parent rd_proc_pipe handle %p for forked child %d after exec, %E";
else if (!DuplicateHandle (parent, herr = from.hProcess, GetCurrentProcess (),
&hProcess, 0, false, DUPLICATE_SAME_ACCESS))
duperr = "couldn't duplicate parent process handle %p for forked child %d after exec, %E";
else
{
h = NULL;
DuplicateHandle (parent, from.h, GetCurrentProcess (), &h, 0, false,
DUPLICATE_SAME_ACCESS);
init (pid, PID_MAP_RW, h);
if (*this)
return;
}
if (duperr)
debug_printf (duperr, herr, pid);
/* Returning with procinfo == NULL. Any open handles will be closed by the
destructor. */
}
const char * const char *
_pinfo::_ctty (char *buf) _pinfo::_ctty (char *buf)
{ {
@ -868,6 +915,7 @@ proc_waiter (void *arg)
si.si_stime = pchildren[rc].rusage_self.ru_stime; si.si_stime = pchildren[rc].rusage_self.ru_stime;
#endif #endif
pid_t pid = vchild->pid; pid_t pid = vchild->pid;
bool its_me = vchild == myself;
for (;;) for (;;)
{ {
@ -881,6 +929,9 @@ proc_waiter (void *arg)
break; break;
} }
if (!its_me && have_execed_cygwin)
break;
si.si_uid = vchild->uid; si.si_uid = vchild->uid;
switch (buf) switch (buf)
@ -889,8 +940,6 @@ proc_waiter (void *arg)
continue; continue;
case 0: case 0:
/* Child exited. Do some cleanup and signal myself. */ /* Child exited. Do some cleanup and signal myself. */
CloseHandle (vchild.rd_proc_pipe);
vchild.rd_proc_pipe = NULL;
vchild.maybe_set_exit_code_from_windows (); vchild.maybe_set_exit_code_from_windows ();
if (WIFEXITED (vchild->exitcode)) if (WIFEXITED (vchild->exitcode))
si.si_code = CLD_EXITED; si.si_code = CLD_EXITED;
@ -918,15 +967,8 @@ proc_waiter (void *arg)
continue; continue;
} }
/* Special case: If the "child process" that died is us, then we're if (its_me && ch_spawn.signal_myself_exited ())
execing. Just call proc_subproc directly and then exit this loop. break;
We're done here. */
if (hExeced)
{
/* execing. no signals available now. */
proc_subproc (PROC_CLEARWAIT, 0);
break;
}
/* Send a SIGCHLD to myself. We do this here, rather than in proc_subproc /* Send a SIGCHLD to myself. We do this here, rather than in proc_subproc
to avoid the proc_subproc lock since the signal thread will eventually to avoid the proc_subproc lock since the signal thread will eventually
@ -1003,13 +1045,13 @@ pinfo::wait ()
waiter_ready = false; waiter_ready = false;
/* Fire up a new thread to track the subprocess */ /* Fire up a new thread to track the subprocess */
cygthread *h = new cygthread (proc_waiter, this, "proc_waiter"); cygthread *h = new cygthread (proc_waiter, this, "waitproc");
if (!h) if (!h)
sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid); sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid);
else else
{ {
wait_thread = h; wait_thread = h;
sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_pipe %p", sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_proc_pipe %p",
(*this)->pid, (*this)->dwProcessId, rd_proc_pipe); (*this)->pid, (*this)->dwProcessId, rd_proc_pipe);
} }
@ -1036,7 +1078,7 @@ _pinfo::alert_parent (char sig)
FIXME: Is there a race here if we run this while another thread is attempting FIXME: Is there a race here if we run this while another thread is attempting
to exec()? */ to exec()? */
if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || hExeced) if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || have_execed)
/* no parent */; /* no parent */;
else else
{ {
@ -1059,17 +1101,19 @@ _pinfo::alert_parent (char sig)
void void
pinfo::release () pinfo::release ()
{ {
if (procinfo) _pinfo_release ();
HANDLE close_h;
if (rd_proc_pipe)
{ {
void *unmap_procinfo = procinfo; close_h = rd_proc_pipe;
procinfo = NULL; rd_proc_pipe = NULL;
UnmapViewOfFile (unmap_procinfo); ForceCloseHandle1 (close_h, rd_proc_pipe);
} }
if (h) if (hProcess)
{ {
HANDLE close_h = h; close_h = hProcess;
h = NULL; hProcess = NULL;
ForceCloseHandle1 (close_h, pinfo_shared_handle); ForceCloseHandle1 (close_h, childhProc);
} }
} }
@ -1145,15 +1189,15 @@ winpids::add (DWORD& nelem, bool winpid, DWORD pid)
} }
pinfo& p = pinfolist[nelem]; pinfo& p = pinfolist[nelem];
memset (&p, 0, sizeof (p));
/* Open a the process to prevent a subsequent exit from invalidating the /* Open a process to prevent a subsequent exit from invalidating the
shared memory region. */ shared memory region. */
p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, pid); p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, pid);
_onreturn onreturn (p.hProcess); _onreturn onreturn (p.hProcess);
/* If we couldn't open the process then we don't have rights to it and should /* If we couldn't open the process then we don't have rights to it and should
make a copy of the shared memory area if it exists (it may not). make a copy of the shared memory area if it exists (it may not). */
*/
bool perform_copy; bool perform_copy;
if (!p.hProcess) if (!p.hProcess)
perform_copy = true; perform_copy = true;
@ -1226,8 +1270,7 @@ out:
else else
{ {
*pnew = *p.procinfo; *pnew = *p.procinfo;
if ((_pinfo *) p != (_pinfo *) myself) p.release ();
p.release ();
p.procinfo = pnew; p.procinfo = pnew;
p.destroy = false; p.destroy = false;
} }
@ -1344,11 +1387,7 @@ winpids::release ()
if (pinfolist[i] == (_pinfo *) myself) if (pinfolist[i] == (_pinfo *) myself)
continue; continue;
else if (pinfolist[i].hProcess) else if (pinfolist[i].hProcess)
{ pinfolist[i].release ();
if (pinfolist[i])
pinfolist[i].release ();
CloseHandle (pinfolist[i].hProcess);
}
else if ((p = pinfolist[i])) else if ((p = pinfolist[i]))
{ {
pinfolist[i].procinfo = NULL; pinfolist[i].procinfo = NULL;

View File

@ -125,7 +125,7 @@ public:
public: public:
HANDLE wr_proc_pipe; HANDLE wr_proc_pipe;
DWORD wr_proc_pipe_owner; DWORD wr_proc_pipe_owner;
friend class pinfo; friend class pinfo_minimal;
}; };
DWORD WINAPI commune_process (void *); DWORD WINAPI commune_process (void *);
@ -136,22 +136,36 @@ enum parent_alerter
__ALERT_ALIVE = 112 __ALERT_ALIVE = 112
}; };
class pinfo class pinfo_minimal
{ {
HANDLE h; HANDLE h;
_pinfo *procinfo;
bool destroy;
public: public:
HANDLE rd_proc_pipe;
HANDLE hProcess; HANDLE hProcess;
HANDLE rd_proc_pipe;
pinfo_minimal (): h (NULL), hProcess (NULL), rd_proc_pipe (NULL) {}
friend class pinfo;
};
class pinfo: public pinfo_minimal
{
bool destroy;
_pinfo *procinfo;
public:
bool waiter_ready; bool waiter_ready;
class cygthread *wait_thread; class cygthread *wait_thread;
void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3))); void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3)));
pinfo (): procinfo (NULL), rd_proc_pipe (NULL) {} pinfo (_pinfo *x = NULL): pinfo_minimal (), destroy (false), procinfo (x),
pinfo (_pinfo *x): procinfo (x), rd_proc_pipe (NULL), hProcess (NULL) {} waiter_ready (false), wait_thread (NULL) {}
pinfo (pid_t n) : rd_proc_pipe (NULL), hProcess (NULL) {init (n, 0, NULL);} pinfo (pid_t n, DWORD flag = 0): pinfo_minimal (), destroy (false),
pinfo (pid_t n, DWORD flag) : rd_proc_pipe (NULL), hProcess (NULL), waiter_ready (0), wait_thread (NULL) {init (n, flag, NULL);} procinfo (NULL), waiter_ready (false),
wait_thread (NULL)
{
init (n, flag, NULL);
}
pinfo (HANDLE, pinfo_minimal&, pid_t);
void thisproc (HANDLE) __attribute__ ((regparm (2))); void thisproc (HANDLE) __attribute__ ((regparm (2)));
inline void _pinfo_release ();
void release (); void release ();
bool wait () __attribute__ ((regparm (1))); bool wait () __attribute__ ((regparm (1)));
~pinfo () ~pinfo ()
@ -172,6 +186,7 @@ public:
_pinfo *operator * () const {return procinfo;} _pinfo *operator * () const {return procinfo;}
operator _pinfo * () const {return procinfo;} operator _pinfo * () const {return procinfo;}
void preserve () { destroy = false; } void preserve () { destroy = false; }
void allow_remove () { destroy = true; }
#ifndef _SIGPROC_H #ifndef _SIGPROC_H
int reattach () {system_printf ("reattach is not here"); return 0;} int reattach () {system_printf ("reattach is not here"); return 0;}
int remember () {system_printf ("remember is not here"); return 0;} int remember () {system_printf ("remember is not here"); return 0;}
@ -255,9 +270,9 @@ public:
#define _P_VFORK 0 #define _P_VFORK 0
#define _P_SYSTEM 512 #define _P_SYSTEM 512
/* Add this flag in calls to spawn_guts if the calling function is one of /* Add this flag in calls to child_info_spawn::worker if the calling function
'p' type functions: execlp, execvp, spawnlp, spawnvp. Per POSIX, only is one of 'p' type functions: execlp, execvp, spawnlp, spawnvp. Per POSIX,
these p-type functions fall back to call /bin/sh if the file is not a only these p-type functions fall back to call /bin/sh if the file is not a
binary. The setting of _P_PATH_TYPE_EXEC is used as a bool value in binary. The setting of _P_PATH_TYPE_EXEC is used as a bool value in
av::fixup to decide if the file should be evaluated as a script, or if av::fixup to decide if the file should be evaluated as a script, or if
ENOEXEC should be returned. */ ENOEXEC should be returned. */

View File

@ -609,7 +609,7 @@ sigwaitinfo (const sigset_t *set, siginfo_t *info)
res = -1; res = -1;
} }
CloseHandle (h); CloseHandle (h);
sigproc_printf ("returning sig %d", res); sigproc_printf ("returning signal %d", res);
return res; return res;
} }

View File

@ -17,11 +17,11 @@ details. */
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h" #include "dtable.h"
#include "sigproc.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info_magic.h" #include "child_info_magic.h"
#include "shared_info.h" #include "shared_info.h"
#include "cygtls.h" #include "cygtls.h"
#include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"
#include "ntdll.h" #include "ntdll.h"
@ -278,9 +278,16 @@ proc_subproc (DWORD what, DWORD val)
w = waitq_head.next; w = waitq_head.next;
waitq_head.next = wval; /* Add at the beginning. */ waitq_head.next = wval; /* Add at the beginning. */
wval->next = w; /* Link in rest of the list. */ wval->next = w; /* Link in rest of the list. */
clearing = 0; clearing = false;
goto scan_wait; goto scan_wait;
case PROC_EXEC_CLEANUP:
while (nprocs)
remove_proc (0);
for (w = &waitq_head; w->next != NULL; w = w->next)
CloseHandle (w->next->ev);
break;
/* Clear all waiting threads. Called from exceptions.cc prior to /* Clear all waiting threads. Called from exceptions.cc prior to
the main thread's dispatch to a signal handler function. the main thread's dispatch to a signal handler function.
(called from wait_sig thread) */ (called from wait_sig thread) */
@ -374,23 +381,11 @@ proc_terminate ()
proc_subproc (PROC_CLEARWAIT, 1); proc_subproc (PROC_CLEARWAIT, 1);
/* Clean out proc processes from the pid list. */ /* Clean out proc processes from the pid list. */
int i; for (int i = 0; i < nprocs; i++)
for (i = 0; i < nprocs; i++)
{ {
/* FIXME: Resetting the ppid to 1 when this process execs is decidedly procs[i]->ppid = 1;
non-UNIXy. We should, at the very least, keep a list of pids
for the exec process to reset when *it* exits. However, avoiding
setting ppid when we are exec'ing causes the ppid to *never* be
set to 1 so we don't do that either.
if (!hExeced)
*/
if (!hExeced || ISSTATE (myself, PID_NOTCYGWIN))
procs[i]->ppid = 1;
if (procs[i].wait_thread) if (procs[i].wait_thread)
{ procs[i].wait_thread->terminate_thread ();
// CloseHandle (procs[i].rd_proc_pipe);
procs[i].wait_thread->terminate_thread ();
}
procs[i].release (); procs[i].release ();
} }
nprocs = 0; nprocs = 0;
@ -477,10 +472,10 @@ sigproc_init ()
api_fatal ("couldn't create signal pipe, %E"); api_fatal ("couldn't create signal pipe, %E");
ProtectHandle (my_readsig); ProtectHandle (my_readsig);
myself->sendsig = my_sendsig; myself->sendsig = my_sendsig;
new cygthread (wait_sig, cygself, "sig");
/* sync_proc_subproc is used by proc_subproc. It serializes /* sync_proc_subproc is used by proc_subproc. It serializes
access to the children and proc arrays. */ access to the children and proc arrays. */
sync_proc_subproc.init ("sync_proc_subproc"); sync_proc_subproc.init ("sync_proc_subproc");
new cygthread (wait_sig, cygself, "sig");
} }
/* Called on process termination to terminate signal and process threads. /* Called on process termination to terminate signal and process threads.
@ -545,7 +540,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
pack.wakeup = NULL; pack.wakeup = NULL;
bool wait_for_completion; bool wait_for_completion;
if (!(its_me = (!hExeced && (p == NULL || p == myself || p == myself_nowait)))) if (!(its_me = (!have_execed && (p == NULL || p == myself || p == myself_nowait))))
{ {
/* It is possible that the process is not yet ready to receive messages /* It is possible that the process is not yet ready to receive messages
* or that it has exited. Detect this. * or that it has exited. Detect this.
@ -760,12 +755,12 @@ out:
} }
int child_info::retry_count = 10; int child_info::retry_count = 10;
/* Initialize some of the memory block passed to child processes /* Initialize some of the memory block passed to child processes
by fork/spawn/exec. */ by fork/spawn/exec. */
child_info::child_info (unsigned in_cb, child_info_types chtype,
child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subproc_ready) bool need_subproc_ready)
{ {
memset (this, 0, in_cb);
cb = in_cb; cb = in_cb;
/* It appears that when running under WOW64 on Vista 64, the first DWORD /* It appears that when running under WOW64 on Vista 64, the first DWORD
@ -827,13 +822,59 @@ child_info::~child_info ()
} }
child_info_fork::child_info_fork () : child_info_fork::child_info_fork () :
child_info (sizeof *this, _PROC_FORK, true) child_info (sizeof *this, _CH_FORK, true)
{ {
} }
child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_ready) : child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_ready) :
child_info (sizeof *this, chtype, need_subproc_ready) child_info (sizeof *this, chtype, need_subproc_ready)
{ {
if (type == _CH_EXEC)
{
hExeced = NULL;
if (myself->wr_proc_pipe)
ev = NULL;
else if (!(ev = CreateEvent (&sec_none_nih, false, false, NULL)))
api_fatal ("couldn't create signalling event for exec, %E");
get_proc_lock (PROC_EXECING, 0);
lock = &sync_proc_subproc;
/* exit with lock held */
}
}
void
child_info_spawn::cleanup ()
{
if (moreinfo)
{
if (moreinfo->envp)
{
for (char **e = moreinfo->envp; *e; e++)
cfree (*e);
cfree (moreinfo->envp);
}
if (type != _CH_SPAWN && moreinfo->myself_pinfo)
CloseHandle (moreinfo->myself_pinfo);
cfree (moreinfo);
}
moreinfo = NULL;
nchildren = 0;
if (ev)
{
CloseHandle (ev);
ev = NULL;
}
debug_printf ("type %d, type == _CH_EXEC == %d, hExeced %p", type, type == _CH_EXEC, hExeced);
if (type == _CH_EXEC)
{
if (iscygwin () && hExeced)
{debug_printf ("cleaning up");
proc_subproc (PROC_EXEC_CLEANUP, 0);
}
sync_proc_subproc.release ();
}
type = _CH_NADA;
} }
/* Record any non-reaped subprocesses to be passed to about-to-be-execed /* Record any non-reaped subprocesses to be passed to about-to-be-execed
@ -842,12 +883,12 @@ child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_r
void void
child_info_spawn::record_children () child_info_spawn::record_children ()
{ {
/* FIXME: locking */ if (type == _CH_EXEC && iscygwin ())
for (nchildren = 0; nchildren < nprocs; nchildren++) for (nchildren = 0; nchildren < nprocs; nchildren++)
{ {
children[nchildren].pid = procs[nchildren]->pid; children[nchildren].pid = procs[nchildren]->pid;
children[nchildren].rd_proc_pipe = procs[nchildren].rd_proc_pipe; children[nchildren].p = procs[nchildren];
} }
} }
/* Reattach non-reaped subprocesses passed in from the cygwin process /* Reattach non-reaped subprocesses passed in from the cygwin process
@ -858,21 +899,15 @@ child_info_spawn::reattach_children ()
{ {
for (int i = 0; i < nchildren; i++) for (int i = 0; i < nchildren; i++)
{ {
pinfo p (children[i].pid, PID_MAP_RW); pinfo p (parent, children[i].p, children[i].pid);
if (!p) if (!p)
/* pid no longer exists */; debug_only_printf ("couldn't reattach child %d from previous process", children[i].pid);
else if (!DuplicateHandle (parent, children[i].rd_proc_pipe,
GetCurrentProcess (), &p.rd_proc_pipe, 0,
false, DUPLICATE_SAME_ACCESS))
debug_printf ("couldn't duplicate parent %p handles for forked children after exec, %E",
children[i].rd_proc_pipe);
else if (!(p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, p->dwProcessId)))
CloseHandle (p.rd_proc_pipe);
else if (!p.reattach ()) else if (!p.reattach ())
{ debug_only_printf ("attach of child process %d failed", children[i].pid);
CloseHandle (p.hProcess); else
CloseHandle (p.rd_proc_pipe); debug_only_printf ("reattached pid %d<%u>, process handle %p, rd_proc_pipe %p->%p",
} p->pid, p->dwProcessId, p.hProcess,
children[i].p.rd_proc_pipe, p.rd_proc_pipe);
} }
} }
@ -888,7 +923,7 @@ child_info::ready (bool execed)
if (dynamically_loaded) if (dynamically_loaded)
sigproc_printf ("not really ready"); sigproc_printf ("not really ready");
else if (!SetEvent (subproc_ready)) else if (!SetEvent (subproc_ready))
api_fatal ("SetEvent failed"); api_fatal ("SetEvent failed, %E");
else else
sigproc_printf ("signalled %p that I was ready", subproc_ready); sigproc_printf ("signalled %p that I was ready", subproc_ready);
@ -935,7 +970,7 @@ child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
{ {
res = true; res = true;
exit_code = STILL_ACTIVE; exit_code = STILL_ACTIVE;
if (type == _PROC_EXEC && myself->wr_proc_pipe) if (type == _CH_EXEC && myself->wr_proc_pipe)
{ {
ForceCloseHandle1 (hProcess, childhProc); ForceCloseHandle1 (hProcess, childhProc);
hProcess = NULL; hProcess = NULL;
@ -1040,17 +1075,15 @@ out:
static bool __stdcall static bool __stdcall
remove_proc (int ci) remove_proc (int ci)
{ {
if (procs[ci]->exists ()) if (have_execed)
procs[ci].wait_thread->terminate_thread ();
else if (procs[ci]->exists ())
return true; return true;
sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid, sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid,
nprocs); nprocs);
if (procs[ci] != myself) if (procs[ci] != myself)
{ procs[ci].release ();
procs[ci].release ();
if (procs[ci].hProcess)
ForceCloseHandle1 (procs[ci].hProcess, childhProc);
}
if (ci < --nprocs) if (ci < --nprocs)
{ {
/* Wait for proc_waiter thread to make a copy of this element before /* Wait for proc_waiter thread to make a copy of this element before
@ -1101,7 +1134,7 @@ stopped_or_terminated (waitq *parent_w, _pinfo *child)
if (!terminated) if (!terminated)
{ {
sigproc_printf ("stopped child, stopsig %d", child->stopsig); sigproc_printf ("stopped child, stop signal %d", child->stopsig);
if (child->stopsig == SIGCONT) if (child->stopsig == SIGCONT)
w->status = __W_CONTINUED; w->status = __W_CONTINUED;
else else
@ -1292,7 +1325,7 @@ wait_sig (VOID *)
// We need a per-thread queue since each thread can have its own // We need a per-thread queue since each thread can have its own
// list of blocked signals. CGF 2005-08-24 // list of blocked signals. CGF 2005-08-24
if (sigq.sigs[sig].si.si_signo && sigq.sigs[sig].tls == pack.tls) if (sigq.sigs[sig].si.si_signo && sigq.sigs[sig].tls == pack.tls)
sigproc_printf ("sig %d already queued", pack.si.si_signo); sigproc_printf ("signal %d already queued", pack.si.si_signo);
else else
{ {
int sigres = pack.process (); int sigres = pack.process ();

View File

@ -35,10 +35,12 @@ enum procstuff
{ {
PROC_ADDCHILD = 1, // add a new subprocess to list PROC_ADDCHILD = 1, // add a new subprocess to list
PROC_REATTACH_CHILD = 2, // reattach after exec PROC_REATTACH_CHILD = 2, // reattach after exec
PROC_DETACHED_CHILD = 3, // set up a detached child PROC_EXEC_CLEANUP = 3, // cleanup waiting children after exec
PROC_CLEARWAIT = 4, // clear all waits - signal arrived PROC_DETACHED_CHILD = 4, // set up a detached child
PROC_WAIT = 5, // setup for wait() for subproc PROC_CLEARWAIT = 5, // clear all waits - signal arrived
PROC_NOTHING = 6 // nothing, really PROC_WAIT = 6, // setup for wait() for subproc
PROC_EXECING = 7, // used to get a lock when execing
PROC_NOTHING = 8 // nothing, really
}; };
struct sigpacket struct sigpacket

View File

@ -56,8 +56,6 @@ static suffix_info dll_suffixes[] =
}; };
#endif #endif
child_info_spawn NO_COPY *chExeced;
/* Add .exe to PROG if not already present and see if that exists. /* Add .exe to PROG if not already present and see if that exists.
If not, return PROG (converted from posix to win32 rules if necessary). If not, return PROG (converted from posix to win32 rules if necessary).
The result is always BUF. The result is always BUF.
@ -219,7 +217,7 @@ find_exec (const char *name, path_conv& buf, const char *mywinenv,
return retval; return retval;
} }
/* Utility for spawn_guts. */ /* Utility for child_info_spawn::worker. */
static HANDLE static HANDLE
handle (int fd, bool writing) handle (int fd, bool writing)
@ -271,10 +269,12 @@ do_cleanup (void *args)
# undef cleanup # undef cleanup
} }
NO_COPY child_info_spawn ch_spawn;
int int
spawn_guts (const char *prog_arg, const char *const *argv, child_info_spawn::worker (const char *prog_arg, const char *const *argv,
const char *const envp[], int mode, int __stdin, int __stdout) const char *const envp[], int mode,
int in__stdin, int in__stdout)
{ {
bool rc; bool rc;
pid_t cygpid; pid_t cygpid;
@ -298,7 +298,7 @@ spawn_guts (const char *prog_arg, const char *const *argv,
return -1; return -1;
} }
syscall_printf ("spawn_guts (%d, %.9500s)", mode, prog_arg); syscall_printf ("mode = %d, prog_arg = %.9500s", mode, prog_arg);
/* FIXME: This is no error condition on Linux. */ /* FIXME: This is no error condition on Linux. */
if (argv == NULL) if (argv == NULL)
@ -323,7 +323,6 @@ spawn_guts (const char *prog_arg, const char *const *argv,
pthread_cleanup_push (do_cleanup, (void *) &cleanup); pthread_cleanup_push (do_cleanup, (void *) &cleanup);
av newargv; av newargv;
linebuf one_line; linebuf one_line;
child_info_spawn ch;
PWCHAR envblock = NULL; PWCHAR envblock = NULL;
path_conv real_path; path_conv real_path;
bool reset_sendsig = false; bool reset_sendsig = false;
@ -332,7 +331,6 @@ spawn_guts (const char *prog_arg, const char *const *argv,
PWCHAR runpath = tp.w_get (); PWCHAR runpath = tp.w_get ();
int c_flags; int c_flags;
bool wascygexec; bool wascygexec;
cygheap_exec_info *moreinfo;
bool null_app_name = false; bool null_app_name = false;
STARTUPINFOW si = {}; STARTUPINFOW si = {};
@ -352,9 +350,9 @@ spawn_guts (const char *prog_arg, const char *const *argv,
child_info_types chtype; child_info_types chtype;
if (mode != _P_OVERLAY) if (mode != _P_OVERLAY)
chtype = PROC_SPAWN; chtype = _CH_SPAWN;
else else
chtype = PROC_EXEC; chtype = _CH_EXEC;
moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1, moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
sizeof (cygheap_exec_info)); sizeof (cygheap_exec_info));
@ -384,12 +382,12 @@ spawn_guts (const char *prog_arg, const char *const *argv,
if (res) if (res)
goto out; goto out;
if (!real_path.iscygexec () && cygheap->cwd.get_error ()) if (!real_path.iscygexec () && ::cygheap->cwd.get_error ())
{ {
small_printf ("Error: Current working directory %s.\n" small_printf ("Error: Current working directory %s.\n"
"Can't start native Windows application from here.\n\n", "Can't start native Windows application from here.\n\n",
cygheap->cwd.get_error_desc ()); ::cygheap->cwd.get_error_desc ());
set_errno (cygheap->cwd.get_error ()); set_errno (::cygheap->cwd.get_error ());
res = -1; res = -1;
goto out; goto out;
} }
@ -447,8 +445,8 @@ spawn_guts (const char *prog_arg, const char *const *argv,
/* Set up needed handles for stdio */ /* Set up needed handles for stdio */
si.dwFlags = STARTF_USESTDHANDLES; si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = handle ((__stdin < 0 ? 0 : __stdin), false); si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
si.hStdOutput = handle ((__stdout < 0 ? 1 : __stdout), true); si.hStdOutput = handle ((in__stdout < 0 ? 1 : in__stdout), true);
si.hStdError = handle (2, true); si.hStdError = handle (2, true);
si.cb = sizeof (si); si.cb = sizeof (si);
@ -479,12 +477,12 @@ spawn_guts (const char *prog_arg, const char *const *argv,
/* Save a copy of a handle to the current process around the first time we /* Save a copy of a handle to the current process around the first time we
exec so that the pid will not be reused. Why did I stop cygwin from exec so that the pid will not be reused. Why did I stop cygwin from
generating its own pids again? */ generating its own pids again? */
if (cygheap->pid_handle) if (::cygheap->pid_handle)
/* already done previously */; /* already done previously */;
else if (DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (), else if (DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
GetCurrentProcess (), &cygheap->pid_handle, GetCurrentProcess (), &::cygheap->pid_handle,
PROCESS_QUERY_INFORMATION, TRUE, 0)) PROCESS_QUERY_INFORMATION, TRUE, 0))
ProtectHandleINH (cygheap->pid_handle); ProtectHandleINH (::cygheap->pid_handle);
else else
system_printf ("duplicate to pid_handle failed, %E"); system_printf ("duplicate to pid_handle failed, %E");
} }
@ -529,10 +527,10 @@ spawn_guts (const char *prog_arg, const char *const *argv,
syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name, syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name,
runpath, wone_line); runpath, wone_line);
cygbench ("spawn-guts"); cygbench ("spawn-worker");
if (!real_path.iscygexec()) if (!real_path.iscygexec())
cygheap->fdtab.set_file_pointers_for_exec (); ::cygheap->fdtab.set_file_pointers_for_exec ();
moreinfo->envp = build_env (envp, envblock, moreinfo->envc, moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
real_path.iscygexec ()); real_path.iscygexec ());
@ -542,23 +540,21 @@ spawn_guts (const char *prog_arg, const char *const *argv,
res = -1; res = -1;
goto out; goto out;
} }
ch.set (chtype, real_path.iscygexec ()); set (chtype, real_path.iscygexec ());
ch.moreinfo = moreinfo; __stdin = in__stdin;
ch.__stdin = __stdin; __stdout = in__stdout;
ch.__stdout = __stdout; record_children ();
if (mode == _P_OVERLAY && ch.iscygwin ())
ch.record_children ();
si.lpReserved2 = (LPBYTE) &ch; si.lpReserved2 = (LPBYTE) this;
si.cbReserved2 = sizeof (ch); si.cbReserved2 = sizeof (*this);
/* Depends on ch.set call above. /* Depends on set call above.
Some file types might need extra effort in the parent after CreateProcess Some file types might need extra effort in the parent after CreateProcess
and before copying the datastructures to the child. So we have to start and before copying the datastructures to the child. So we have to start
the child in suspend state, unfortunately, to avoid a race condition. */ the child in suspend state, unfortunately, to avoid a race condition. */
if (!newargv.win16_exe if (!newargv.win16_exe
&& (!ch.iscygwin () || mode != _P_OVERLAY && (!iscygwin () || mode != _P_OVERLAY
|| cygheap->fdtab.need_fixup_before ())) || ::cygheap->fdtab.need_fixup_before ()))
c_flags |= CREATE_SUSPENDED; c_flags |= CREATE_SUSPENDED;
/* If a native application should be spawned, we test here if the spawning /* If a native application should be spawned, we test here if the spawning
process is running in a console and, if so, if it's a foreground or process is running in a console and, if so, if it's a foreground or
@ -568,26 +564,26 @@ spawn_guts (const char *prog_arg, const char *const *argv,
in a console will break native processes running in the background, in a console will break native processes running in the background,
because the Ctrl-C event is sent to all processes in the console, unless because the Ctrl-C event is sent to all processes in the console, unless
they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */ they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */
if (!ch.iscygwin () && myself->ctty >= 0 && iscons_dev (myself->ctty) if (!iscygwin () && myself->ctty >= 0 && iscons_dev (myself->ctty)
&& fhandler_console::tc_getpgid () != getpgrp ()) && fhandler_console::tc_getpgid () != getpgrp ())
c_flags |= CREATE_NEW_PROCESS_GROUP; c_flags |= CREATE_NEW_PROCESS_GROUP;
ch.refresh_cygheap (); refresh_cygheap ();
/* When ruid != euid we create the new process under the current original /* When ruid != euid we create the new process under the current original
account and impersonate in child, this way maintaining the different account and impersonate in child, this way maintaining the different
effective vs. real ids. effective vs. real ids.
FIXME: If ruid != euid and ruid != saved_uid we currently give FIXME: If ruid != euid and ruid != saved_uid we currently give
up on ruid. The new process will have ruid == euid. */ up on ruid. The new process will have ruid == euid. */
loop: loop:
cygheap->user.deimpersonate (); ::cygheap->user.deimpersonate ();
if (!real_path.iscygexec () && mode == _P_OVERLAY) if (!real_path.iscygexec () && mode == _P_OVERLAY)
myself->process_state |= PID_NOTCYGWIN; myself->process_state |= PID_NOTCYGWIN;
if (!cygheap->user.issetuid () if (!::cygheap->user.issetuid ()
|| (cygheap->user.saved_uid == cygheap->user.real_uid || (::cygheap->user.saved_uid == ::cygheap->user.real_uid
&& cygheap->user.saved_gid == cygheap->user.real_gid && ::cygheap->user.saved_gid == ::cygheap->user.real_gid
&& !cygheap->user.groups.issetgroups () && !::cygheap->user.groups.issetgroups ()
&& !cygheap->user.setuid_to_restricted)) && !::cygheap->user.setuid_to_restricted))
{ {
rc = CreateProcessW (runpath, /* image name - with full path */ rc = CreateProcessW (runpath, /* image name - with full path */
wone_line, /* what was passed to exec */ wone_line, /* what was passed to exec */
@ -621,20 +617,20 @@ loop:
risk, but we don't want to disable this behaviour for older risk, but we don't want to disable this behaviour for older
OSes because it's still heavily used by some users. They have OSes because it's still heavily used by some users. They have
been warned. */ been warned. */
if (!cygheap->user.setuid_to_restricted if (!::cygheap->user.setuid_to_restricted
&& wcscasecmp (wstname, L"WinSta0") != 0) && wcscasecmp (wstname, L"WinSta0") != 0)
{ {
WCHAR sid[128]; WCHAR sid[128];
sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024), sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
cygheap->user.sid ()); ::cygheap->user.sid ());
/* We're creating a window station per user, not per logon session. /* We're creating a window station per user, not per logon session.
First of all we might not have a valid logon session for First of all we might not have a valid logon session for
the user (logon by create_token), and second, it doesn't the user (logon by create_token), and second, it doesn't
make sense in terms of security to create a new window make sense in terms of security to create a new window
station for every logon of the same user. It just fills up station for every logon of the same user. It just fills up
the system with window stations for no good reason. */ the system with window stations for no good reason. */
hwst = CreateWindowStationW (cygheap->user.get_windows_id (sid), 0, hwst = CreateWindowStationW (::cygheap->user.get_windows_id (sid), 0,
GENERIC_READ | GENERIC_WRITE, sa); GENERIC_READ | GENERIC_WRITE, sa);
if (!hwst) if (!hwst)
system_printf ("CreateWindowStation failed, %E"); system_printf ("CreateWindowStation failed, %E");
@ -651,7 +647,7 @@ loop:
} }
} }
rc = CreateProcessAsUserW (cygheap->user.primary_token (), rc = CreateProcessAsUserW (::cygheap->user.primary_token (),
runpath, /* image name - with full path */ runpath, /* image name - with full path */
wone_line, /* what was passed to exec */ wone_line, /* what was passed to exec */
&sec_none_nih, /* process security attrs */ &sec_none_nih, /* process security attrs */
@ -677,7 +673,7 @@ loop:
/* Restore impersonation. In case of _P_OVERLAY this isn't /* Restore impersonation. In case of _P_OVERLAY this isn't
allowed since it would overwrite child data. */ allowed since it would overwrite child data. */
if (mode != _P_OVERLAY || !rc) if (mode != _P_OVERLAY || !rc)
cygheap->user.reimpersonate (); ::cygheap->user.reimpersonate ();
/* Set errno now so that debugging messages from it appear before our /* Set errno now so that debugging messages from it appear before our
final debugging message [this is a general rule for debugging final debugging message [this is a general rule for debugging
@ -698,12 +694,12 @@ loop:
} }
if (!(c_flags & CREATE_SUSPENDED)) if (!(c_flags & CREATE_SUSPENDED))
strace.write_childpid (ch, pi.dwProcessId); strace.write_childpid (*this, pi.dwProcessId);
/* Fixup the parent data structures if needed and resume the child's /* Fixup the parent data structures if needed and resume the child's
main thread. */ main thread. */
if (cygheap->fdtab.need_fixup_before ()) if (::cygheap->fdtab.need_fixup_before ())
cygheap->fdtab.fixup_before_exec (pi.dwProcessId); ::cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
if (mode != _P_OVERLAY) if (mode != _P_OVERLAY)
cygpid = cygwin_pid (pi.dwProcessId); cygpid = cygwin_pid (pi.dwProcessId);
@ -711,7 +707,7 @@ loop:
cygpid = myself->pid; cygpid = myself->pid;
/* We print the original program name here so the user can see that too. */ /* We print the original program name here so the user can see that too. */
syscall_printf ("%d = spawn_guts (%s, %.9500s)", syscall_printf ("%d = child_info_spawn::worker (%s, %.9500s)",
rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf); rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
/* Name the handle similarly to proc_subproc. */ /* Name the handle similarly to proc_subproc. */
@ -721,7 +717,6 @@ loop:
pid_t pid; pid_t pid;
if (mode == _P_OVERLAY) if (mode == _P_OVERLAY)
{ {
chExeced = &ch; /* FIXME: there's a race here if a user sneaks in CTRL-C */
myself->dwProcessId = pi.dwProcessId; myself->dwProcessId = pi.dwProcessId;
strace.execing = 1; strace.execing = 1;
myself.hProcess = hExeced = pi.hProcess; myself.hProcess = hExeced = pi.hProcess;
@ -747,7 +742,7 @@ loop:
orig_wr_proc_pipe = myself->dup_proc_pipe (pi.hProcess); orig_wr_proc_pipe = myself->dup_proc_pipe (pi.hProcess);
} }
pid = myself->pid; pid = myself->pid;
if (!ch.iscygwin ()) if (!iscygwin ())
close_all_files (); close_all_files ();
} }
else else
@ -792,16 +787,16 @@ loop:
if (c_flags & CREATE_SUSPENDED) if (c_flags & CREATE_SUSPENDED)
{ {
ResumeThread (pi.hThread); ResumeThread (pi.hThread);
strace.write_childpid (ch, pi.dwProcessId); strace.write_childpid (*this, pi.dwProcessId);
} }
ForceCloseHandle (pi.hThread); ForceCloseHandle (pi.hThread);
sigproc_printf ("spawned windows pid %d", pi.dwProcessId); sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
if ((mode == _P_DETACH || mode == _P_NOWAIT) && !ch.iscygwin ()) if ((mode == _P_DETACH || mode == _P_NOWAIT) && !iscygwin ())
synced = false; synced = false;
else else
synced = ch.sync (pi.dwProcessId, pi.hProcess, INFINITE); synced = sync (pi.dwProcessId, pi.hProcess, INFINITE);
switch (mode) switch (mode)
{ {
@ -814,7 +809,7 @@ loop:
myself->wr_proc_pipe_owner = GetCurrentProcessId (); myself->wr_proc_pipe_owner = GetCurrentProcessId ();
myself->wr_proc_pipe = orig_wr_proc_pipe; myself->wr_proc_pipe = orig_wr_proc_pipe;
} }
if (!ch.proc_retry (pi.hProcess)) if (!proc_retry (pi.hProcess))
{ {
looped++; looped++;
goto loop; goto loop;
@ -830,9 +825,10 @@ loop:
extern bool is_toplevel_proc; extern bool is_toplevel_proc;
is_toplevel_proc = true; is_toplevel_proc = true;
myself.remember (false); myself.remember (false);
waitpid (myself->pid, &res, 0); wait_for_myself ();
} }
} }
this->cleanup ();
myself.exit (EXITCODE_NOSET); myself.exit (EXITCODE_NOSET);
break; break;
case _P_WAIT: case _P_WAIT:
@ -853,11 +849,12 @@ loop:
} }
out: out:
debug_printf ("about to call cleanup");
this->cleanup ();
if (envblock) if (envblock)
free (envblock); free (envblock);
pthread_cleanup_pop (1); pthread_cleanup_pop (1);
return (int) res; return (int) res;
#undef ch
} }
extern "C" int extern "C" int
@ -895,8 +892,8 @@ spawnve (int mode, const char *path, const char *const *argv,
switch (_P_MODE (mode)) switch (_P_MODE (mode))
{ {
case _P_OVERLAY: case _P_OVERLAY:
spawn_guts (path, argv, envp, mode); ch_spawn.worker (path, argv, envp, mode);
/* Errno should be set by spawn_guts. */ /* Errno should be set by worker. */
ret = -1; ret = -1;
break; break;
case _P_VFORK: case _P_VFORK:
@ -905,7 +902,7 @@ spawnve (int mode, const char *path, const char *const *argv,
case _P_WAIT: case _P_WAIT:
case _P_DETACH: case _P_DETACH:
case _P_SYSTEM: case _P_SYSTEM:
ret = spawn_guts (path, argv, envp, mode); ret = ch_spawn.worker (path, argv, envp, mode);
#ifdef NEWVFORK #ifdef NEWVFORK
if (vf) if (vf)
{ {

View File

@ -63,6 +63,8 @@ details. */
#include "registry.h" #include "registry.h"
#include "environ.h" #include "environ.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include "sync.h"
#include "child_info.h"
#undef _close #undef _close
#undef _lseek #undef _lseek
@ -106,7 +108,7 @@ close_all_files (bool norelease)
cygheap->fdtab.release (i); cygheap->fdtab.release (i);
} }
if (!hExeced && cygheap->ctty) if (!have_execed && cygheap->ctty)
cygheap->close_ctty (); cygheap->close_ctty ();
if (h) if (h)
@ -4154,8 +4156,8 @@ popen (const char *command, const char *in_type)
fcntl64 (stdchild, F_SETFD, stdchild_state | FD_CLOEXEC); fcntl64 (stdchild, F_SETFD, stdchild_state | FD_CLOEXEC);
/* Start a shell process to run the given command without forking. */ /* Start a shell process to run the given command without forking. */
pid_t pid = spawn_guts ("/bin/sh", argv, cur_environ (), _P_NOWAIT, pid_t pid = ch_spawn.worker ("/bin/sh", argv, cur_environ (), _P_NOWAIT,
__std[0], __std[1]); __std[0], __std[1]);
/* Reinstate the close-on-exec state */ /* Reinstate the close-on-exec state */
fcntl64 (stdchild, F_SETFD, stdchild_state); fcntl64 (stdchild, F_SETFD, stdchild_state);

View File

@ -162,7 +162,7 @@ timer_thread (VOID *x)
si.si_signo = tt->evp.sigev_signo; si.si_signo = tt->evp.sigev_signo;
si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr; si.si_sigval.sival_ptr = tt->evp.sigev_value.sival_ptr;
si.si_code = SI_TIMER; si.si_code = SI_TIMER;
debug_printf ("%p sending sig %d", x, tt->evp.sigev_signo); debug_printf ("%p sending signal %d", x, tt->evp.sigev_signo);
sig_send (myself_nowait, si); sig_send (myself_nowait, si);
break; break;
} }

View File

@ -161,9 +161,6 @@ void dll_crt0 (per_process *) __asm__ ("_dll_crt0__FP11per_process");
extern "C" void __stdcall _dll_crt0 (); extern "C" void __stdcall _dll_crt0 ();
void dll_crt0_1 (void *); void dll_crt0_1 (void *);
void dll_dllcrt0_1 (void *); void dll_dllcrt0_1 (void *);
int spawn_guts (const char * prog_arg, const char *const *argv,
const char *const envp[], int mode, int __stdin = -1,
int __stdout = -1) __attribute__ ((regparm(3)));
/* dynamically loaded dll initialization */ /* dynamically loaded dll initialization */
extern "C" int dll_dllcrt0 (HMODULE, per_process *); extern "C" int dll_dllcrt0 (HMODULE, per_process *);