aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2006-03-18 19:17:21 +0000
committerChristopher Faylor <me@cgf.cx>2006-03-18 19:17:21 +0000
commita939686807dd8e832939fddf514040fdba7077d8 (patch)
treee9e816e39dde05a3353c9137c9763f6d474adac9
parent61337a0f4594e1301011b775a6f9672fc58b4ec0 (diff)
downloadnewlib-a939686807dd8e832939fddf514040fdba7077d8.zip
newlib-a939686807dd8e832939fddf514040fdba7077d8.tar.gz
newlib-a939686807dd8e832939fddf514040fdba7077d8.tar.bz2
* child_info.h (CURR_CHILD_INFO_MAGIC): Regenerate.
(child_info::retry): Move here from fork subclass. (child_info::exit_code): New field. (child_info::retry_count): Max retry count for process start. (child_info::proc_retry): Declare new function. (child_info_fork::retry): Move to parent. (child_info_fork::fork_retry): Ditto. * dcrt0.cc (child_info::fork_retry): Rename and move. (child_info_fork::handle_failure): Move. (dll_crt0_0): Initialize console handler based on whether we have a controlling tty or not. Avoid nonsensical check for fork where it can never occur. * environ.cc (set_proc_retry): Rename from set_fork_retry. Set retry_count in child_info. (parse_thing): Reflect above change. * exceptions.cc (dummy_ctrl_c_handler): Remove unused variable name. (ctrl_c_handler): Always return TRUE for the annoying CTRL_LOGOFF_EVENT. * fhandler_termios.cc (fhandler_termios::tcsetpgrp): Remove call to init_console_handler. * fhandler_tty.cc (fhandler_tty_slave::open): Just call mange_console_count here and let it decide what to do with initializing console control handling. * fork.cc (fork_retry): Remove definition. (frok::parent): Define static errbuf and use in error messages (not thread safe yet). Close pi.hThread as soon as possible. Protect pi.hProcess as soon as possible. Don't set retry_count. That happens automatically in the constructor now. Accommodate name change from fork_retry to proc_retry. * init.cc (dll_entry): Turn off ctrl-c handling early until we know how it is supposed to be handled. * pinfo.cc (_pinfo::dup_proc_pipe): Remember original proc pipe value for failure error message. Tweak debug message slightly. * sigproc.cc (child_info::retry_count): Define. (child_info::child_info): Initialize retry count. (child_info::sync): Set exit code if process dies before synchronization. (child_info::proc_retry): Rename from child_info_fork::fork_retry. Use previously derived exit code. Be more defensive about what is classified as an error exit. (child_info_fork::handle_failure): Move here from dcrt0.cc. * spawn.cc (spawn_guts): Maintain error mode when starting new process to avoid annoying pop ups. Move deimpersonate call within new loop. Move envblock freeing to end. Loop if process dies prematurely with bad exit code. * syscalls.cc (init_console_handler): Remove hopefully unneeded call to init_console_handler.
-rw-r--r--winsup/cygwin/ChangeLog50
-rw-r--r--winsup/cygwin/child_info.h8
-rw-r--r--winsup/cygwin/dcrt0.cc33
-rw-r--r--winsup/cygwin/environ.cc7
-rw-r--r--winsup/cygwin/exceptions.cc6
-rw-r--r--winsup/cygwin/fhandler_termios.cc1
-rw-r--r--winsup/cygwin/fhandler_tty.cc4
-rw-r--r--winsup/cygwin/fork.cc40
-rw-r--r--winsup/cygwin/init.cc5
-rw-r--r--winsup/cygwin/pinfo.cc8
-rw-r--r--winsup/cygwin/sigproc.cc50
-rw-r--r--winsup/cygwin/spawn.cc40
-rw-r--r--winsup/cygwin/syscalls.cc1
-rw-r--r--winsup/cygwin/winsup.h3
14 files changed, 170 insertions, 86 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index cb12f15..aaeac47 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,53 @@
+2006-03-18 Christopher Faylor <cgf@timesys.com>
+
+ * child_info.h (CURR_CHILD_INFO_MAGIC): Regenerate.
+ (child_info::retry): Move here from fork subclass.
+ (child_info::exit_code): New field.
+ (child_info::retry_count): Max retry count for process start.
+ (child_info::proc_retry): Declare new function.
+ (child_info_fork::retry): Move to parent.
+ (child_info_fork::fork_retry): Ditto.
+ * dcrt0.cc (child_info::fork_retry): Rename and move.
+ (child_info_fork::handle_failure): Move.
+ (dll_crt0_0): Initialize console handler based on whether we have a
+ controlling tty or not. Avoid nonsensical check for fork where it can
+ never occur.
+ * environ.cc (set_proc_retry): Rename from set_fork_retry. Set
+ retry_count in child_info.
+ (parse_thing): Reflect above change.
+ * exceptions.cc (dummy_ctrl_c_handler): Remove unused variable name.
+ (ctrl_c_handler): Always return TRUE for the annoying
+ CTRL_LOGOFF_EVENT.
+ * fhandler_termios.cc (fhandler_termios::tcsetpgrp): Remove call to
+ init_console_handler.
+ * fhandler_tty.cc (fhandler_tty_slave::open): Just call
+ mange_console_count here and let it decide what to do with initializing
+ console control handling.
+ * fork.cc (fork_retry): Remove definition.
+ (frok::parent): Define static errbuf and use in error messages (not
+ thread safe yet). Close pi.hThread as soon as possible. Protect
+ pi.hProcess as soon as possible. Don't set retry_count. That happens
+ automatically in the constructor now. Accommodate name change from
+ fork_retry to proc_retry.
+ * init.cc (dll_entry): Turn off ctrl-c handling early until we know how
+ it is supposed to be handled.
+ * pinfo.cc (_pinfo::dup_proc_pipe): Remember original proc pipe value
+ for failure error message. Tweak debug message slightly.
+ * sigproc.cc (child_info::retry_count): Define.
+ (child_info::child_info): Initialize retry count.
+ (child_info::sync): Set exit code if process dies before
+ synchronization.
+ (child_info::proc_retry): Rename from child_info_fork::fork_retry. Use
+ previously derived exit code. Be more defensive about what is
+ classified as an error exit.
+ (child_info_fork::handle_failure): Move here from dcrt0.cc.
+ * spawn.cc (spawn_guts): Maintain error mode when starting new process
+ to avoid annoying pop ups. Move deimpersonate call within new loop.
+ Move envblock freeing to end. Loop if process dies prematurely with
+ bad exit code.
+ * syscalls.cc (init_console_handler): Remove hopefully unneeded call to
+ init_console_handler.
+
2006-03-15 Christopher Faylor <cgf@timesys.com>
* cygheap.cc (init_cygheap::manage_console_count): Turn console control
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 87da6e4..efca034 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -29,7 +29,7 @@ enum child_info_types
#define EXEC_MAGIC_SIZE sizeof(child_info)
-#define CURR_CHILD_INFO_MAGIC 0x88e640f7U
+#define CURR_CHILD_INFO_MAGIC 0x482b2eaU
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@@ -50,11 +50,15 @@ public:
DWORD cygheap_reserve_sz;
unsigned char straced;
unsigned fhandler_union_cb;
+ int retry; // number of times we've tried to start child process
+ DWORD exit_code; // process exit code
+ static int retry_count;// retry count;
child_info (unsigned, child_info_types, bool);
child_info (): subproc_ready (NULL), parent (NULL) {}
~child_info ();
void ready (bool);
bool sync (int, HANDLE&, DWORD) __attribute__ ((regparm (3)));
+ DWORD proc_retry (HANDLE);
};
class mount_info;
@@ -68,11 +72,9 @@ public:
jmp_buf jmp; // where child will jump to
void *stacktop; // location of top of parent stack
void *stackbottom; // location of bottom of parent stack
- int retry; // number of times we've tried to fork
child_info_fork ();
void handle_fork ();
bool handle_failure (DWORD);
- DWORD fork_retry (HANDLE);
};
class fhandler_base;
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index c309fb3..52281c9 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -642,33 +642,6 @@ get_cygwin_startup_info ()
return res;
}
-DWORD
-child_info_fork::fork_retry (HANDLE h)
-{
- DWORD exit_code;
- if (!GetExitCodeProcess (h, &exit_code))
- return STILL_ACTIVE; /* should never happen */
- switch (exit_code)
- {
- case STATUS_CONTROL_C_EXIT:
- case STATUS_DLL_INIT_FAILED:
- case STATUS_DLL_INIT_FAILED_LOGOFF:
- case EXITCODE_RETRY:
- if (retry-- > 0)
- return 0;
- break;
- }
- return exit_code;
-}
-
-bool
-child_info_fork::handle_failure (DWORD err)
-{
- if (retry > 0)
- ExitProcess (EXITCODE_RETRY);
- return 0;
-}
-
#define dll_data_start &_data_start__
#define dll_data_end &_data_end__
#define dll_bss_start &_bss_start__
@@ -736,7 +709,7 @@ dll_crt0_0 ()
if (!child_proc_info)
{
memory_init ();
- init_console_handler (myself->ctty >= 0);
+ init_console_handler (!!GetConsoleCP ());
}
else
{
@@ -757,8 +730,7 @@ dll_crt0_0 ()
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
h = NULL;
set_myself (h);
- if (child_proc_info->type != _PROC_FORK)
- child_proc_info->ready (true);
+ child_proc_info->ready (true);
__argc = spawn_info->moreinfo->argc;
__argv = spawn_info->moreinfo->argv;
envp = spawn_info->moreinfo->envp;
@@ -773,7 +745,6 @@ dll_crt0_0 ()
}
break;
}
- init_console_handler (myself->ctty >= 0);
}
user_data->resourcelocks->Init ();
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 28bfe39..1c93434 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -39,7 +39,6 @@ static bool envcache = true;
#ifdef USE_SERVER
extern bool allow_server;
#endif
-extern int fork_retry;
static char **lastenviron;
@@ -520,9 +519,9 @@ set_chunksize (const char *buf)
}
static void
-set_fork_retry (const char *buf)
+set_proc_retry (const char *buf)
{
- fork_retry = strtoul (buf, NULL, 0);
+ child_info::retry_count = strtoul (buf, NULL, 0);
}
static void
@@ -594,7 +593,7 @@ static struct parse_thing
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
{"transparent_exe", {&transparent_exe}, justset, NULL, {{false}, {true}}},
- {"fork_retry", {func: set_fork_retry}, isfunc, NULL, {{0}, {5}}},
+ {"proc_retry", {func: set_proc_retry}, isfunc, NULL, {{0}, {5}}},
{NULL, {0}, justset, 0, {{0}, {0}}}
};
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 53294cd..dabfeab 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -94,7 +94,7 @@ NO_COPY static struct
/* Initialization code. */
BOOL WINAPI
-dummy_ctrl_c_handler (DWORD dwCtrlType)
+dummy_ctrl_c_handler (DWORD)
{
return TRUE;
}
@@ -103,6 +103,7 @@ void
init_console_handler (bool install_handler)
{
BOOL res;
+
while (SetConsoleCtrlHandler (ctrl_c_handler, FALSE))
continue;
if (install_handler)
@@ -113,6 +114,7 @@ init_console_handler (bool install_handler)
res = SetConsoleCtrlHandler (dummy_ctrl_c_handler, TRUE);
if (!res)
system_printf ("SetConsoleCtrlHandler failed, %E");
+ return;
}
extern "C" void
@@ -946,7 +948,7 @@ ctrl_c_handler (DWORD type)
if (has_visible_window_station ())
sig_send (myself_nowait, SIGHUP);
#endif
- return FALSE;
+ return TRUE;
}
}
diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc
index 9b1098f..3475f5e 100644
--- a/winsup/cygwin/fhandler_termios.cc
+++ b/winsup/cygwin/fhandler_termios.cc
@@ -82,7 +82,6 @@ fhandler_termios::tcsetpgrp (const pid_t pgid)
{
case bg_ok:
tc->setpgid (pgid);
- init_console_handler (!!is_console ());
res = 0;
break;
case bg_signalled:
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 24ba4e3..2cf551a 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -576,9 +576,7 @@ fhandler_tty_slave::open (int flags, mode_t)
set_output_handle (to_master_local);
set_open_status ();
- if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1
- && !output_done_event && fhandler_console::need_invisible ())
- init_console_handler (TRUE);
+ cygheap->manage_console_count ("fhandler_tty_slave::open", 1);
// FIXME: Do this better someday
arch = (fhandler_tty_slave *) cmalloc (HEAP_ARCHETYPES, sizeof (*this));
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 2609608..0360d1a 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -33,8 +33,6 @@ details. */
#define NPIDS_HELD 4
-int fork_retry = 5;
-
/* Timeout to wait for child to start, parent to init child, etc. */
/* FIXME: Once things stabilize, bump up to a few minutes. */
#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
@@ -171,6 +169,7 @@ frok::child (void *)
sync_with_parent ("loaded dlls", true);
}
+ init_console_handler (myself->ctty >= 0);
ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
pthread::atforkchild ();
@@ -221,6 +220,7 @@ frok::parent (void *stack_here)
this_errno = 0;
bool fix_impersonation = false;
pinfo child;
+ static char errbuf[256];
pthread::atforkprepare ();
@@ -290,7 +290,6 @@ frok::parent (void *stack_here)
myself->progname, myself->progname, c_flags, &si, &pi);
bool locked = __malloc_lock ();
time_t start_time;
- ch.retry = fork_retry;
while (1)
{
start_time = time (NULL);
@@ -321,22 +320,25 @@ frok::parent (void *stack_here)
ResumeThread (pi.hThread);
}
+ CloseHandle (pi.hThread);
+
+ /* Protect the handle but name it similarly to the way it will
+ be called in subproc handling. */
+ ProtectHandle1 (pi.hProcess, childhProc);
+
strace.write_childpid (ch, pi.dwProcessId);
/* Wait for subproc to initialize itself. */
if (!ch.sync (pi.dwProcessId, pi.hProcess, FORK_WAIT_TIMEOUT))
{
- DWORD exit_code = ch.fork_retry (pi.hProcess);
+ DWORD exit_code = ch.proc_retry (pi.hProcess);
if (!exit_code)
continue;
this_errno = EAGAIN;
/* Not thread safe, but do we care? */
- static char buf[sizeof("died waiting for longjmp before "
- "initialization, retry 4294967295, "
- "exit code 0xfffffffff")];
- __small_sprintf (buf, "died waiting for longjmp before initialization, "
+ __small_sprintf (errbuf, "died waiting for longjmp before initialization, "
"retry %d, exit code %p", ch.retry, exit_code);
- error = buf;
+ error = errbuf;
goto cleanup;
}
break;
@@ -367,11 +369,6 @@ frok::parent (void *stack_here)
cygheap->user.reimpersonate ();
fix_impersonation = false;
- ProtectHandle (pi.hThread);
- /* Protect the handle but name it similarly to the way it will
- be called in subproc handling. */
- ProtectHandle1 (pi.hProcess, childhProc);
-
/* Fill in fields in the child's process table entry. */
child->dwProcessId = pi.dwProcessId;
child.hProcess = pi.hProcess;
@@ -426,6 +423,11 @@ frok::parent (void *stack_here)
if (!rc)
{
this_errno = get_errno ();
+ DWORD exit_code;
+ if (!GetExitCodeProcess (pi.hProcess, &exit_code))
+ exit_code = 0xdeadbeef;
+ __small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
+ error = errbuf;
goto cleanup;
}
@@ -440,7 +442,11 @@ frok::parent (void *stack_here)
{
this_errno = get_errno ();
#ifdef DEBUGGING
- error = "fork_copy for linked dll data/bss failed";
+ DWORD exit_code;
+ if (!GetExitCodeProcess (pi.hProcess, &exit_code))
+ exit_code = 0xdeadbeef;
+ __small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
+ error = errbuf;
#endif
goto cleanup;
}
@@ -481,10 +487,8 @@ frok::parent (void *stack_here)
resume_child (forker_finished);
}
- ForceCloseHandle (pi.hThread);
ForceCloseHandle (forker_finished);
forker_finished = NULL;
- pi.hThread = NULL;
pthread::atforkparent ();
return child_pid;
@@ -499,8 +503,6 @@ cleanup:
/* Remember to de-allocate the fd table. */
if (pi.hProcess && !child.hProcess)
ForceCloseHandle1 (pi.hProcess, childhProc);
- if (pi.hThread)
- ForceCloseHandle (pi.hThread);
if (forker_finished)
ForceCloseHandle (forker_finished);
debug_printf ("returning -1");
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 342bb1c..f8b6cd6 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -128,11 +128,12 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
switch (reason)
{
case DLL_PROCESS_ATTACH:
+ wincap.init ();
+ init_console_handler (false);
+
cygwin_hmodule = (HMODULE) h;
dynamically_loaded = (static_load == NULL);
- wincap.init ();
-
/* Is the stack at an unusual address? This is, an address which
is in the usual space occupied by the process image, but below
the auto load address of DLLs?
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 146b432..cacfc79 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -927,7 +927,8 @@ bool
_pinfo::dup_proc_pipe (HANDLE hProcess)
{
DWORD flags = DUPLICATE_SAME_ACCESS;
- /* Grr. Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be
+ HANDLE orig_wr_proc_pipe = wr_proc_pipe;
+ /* Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be
execing a non-cygwin process and we need to set the exit value before the
parent sees it. */
if (this != myself || is_toplevel_proc)
@@ -935,11 +936,12 @@ _pinfo::dup_proc_pipe (HANDLE hProcess)
bool res = DuplicateHandle (hMainProc, wr_proc_pipe, hProcess, &wr_proc_pipe,
0, FALSE, flags);
if (!res && WaitForSingleObject (hProcess, 0) != WAIT_OBJECT_0)
- system_printf ("DuplicateHandle failed, pid %d, hProcess %p, %E", pid, hProcess);
+ system_printf ("DuplicateHandle failed, pid %d, hProcess %p, wr_proc_pipe %p, %E",
+ pid, hProcess, orig_wr_proc_pipe);
else
{
wr_proc_pipe_owner = dwProcessId;
- sigproc_printf ("closed wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
+ sigproc_printf ("duped wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
pid, dwProcessId);
res = true;
}
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 4cd538c..a213a56 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -523,7 +523,7 @@ sig_send (_pinfo *p, int sig)
else
{
#ifdef DEBUGGING
- system_printf ("signal %d sent to %p while signals are on hold", p, sig);
+ system_printf ("signal %d sent to %p while signals are on hold", sig, p);
#endif
return -1;
}
@@ -767,6 +767,7 @@ out:
return rc;
}
+int child_info::retry_count = 10;
/* Initialize some of the memory block passed to child processes
by fork/spawn/exec. */
@@ -785,6 +786,7 @@ child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subpr
cygheap = ::cygheap;
cygheap_max = ::cygheap_max;
straced = strace.attached ();
+ retry = child_info::retry_count;
/* Create an inheritable handle to pass to the child process. This will
allow the child to duplicate handles from the parent to itself. */
parent = NULL;
@@ -862,21 +864,63 @@ child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
else
{
if (x != nsubproc_ready)
- res = type != _PROC_FORK;
+ {
+ res = false;
+ GetExitCodeProcess (hProcess, &exit_code);
+ }
else
{
+ res = true;
+ exit_code = STILL_ACTIVE;
if (type == _PROC_EXEC && myself->wr_proc_pipe)
{
ForceCloseHandle1 (hProcess, childhProc);
hProcess = NULL;
}
- res = true;
}
sigproc_printf ("pid %u, WFMO returned %d, res %d", pid, x, res);
}
return res;
}
+DWORD
+child_info::proc_retry (HANDLE h)
+{
+ switch (exit_code)
+ {
+ case STILL_ACTIVE: /* shouldn't happen */
+ sigproc_printf ("STILL_ACTIVE? How'd we get here?");
+ break;
+ case STATUS_CONTROL_C_EXIT:
+ case STATUS_DLL_INIT_FAILED:
+ case STATUS_DLL_INIT_FAILED_LOGOFF:
+ case EXITCODE_RETRY:
+ if (retry-- > 0)
+ exit_code = 0;
+ break;
+ /* Count down non-recognized exit codes more quickly since they aren't
+ due to known conditions. */
+ default:
+ if ((exit_code & 0xc0000000) != 0xc0000000)
+ break;
+ if ((retry -= 2) < 0)
+ retry = 0;
+ else
+ exit_code = 0;
+ }
+ if (!exit_code)
+ ForceCloseHandle1 (h, childhProc);
+ return exit_code;
+}
+
+bool
+child_info_fork::handle_failure (DWORD err)
+{
+ if (retry > 0)
+ ExitProcess (EXITCODE_RETRY);
+ return 0;
+}
+
/* Check the state of all of our children to see if any are stopped or
* terminated.
*/
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cac02d9..16955bb 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -438,12 +438,13 @@ spawn_guts (const char * prog_arg, const char *const *argv,
linebuf one_line;
child_info_spawn ch;
- char *envblock;
+ char *envblock = NULL;
path_conv real_path;
bool reset_sendsig = false;
bool null_app_name = false;
STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
+ int looped = 0;
myfault efault;
if (efault.faulted ())
@@ -600,7 +601,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
int flags = GetPriorityClass (hMainProc);
sigproc_printf ("priority class %d", flags);
- flags |= CREATE_DEFAULT_ERROR_MODE | CREATE_SEPARATE_WOW_VDM;
+ flags |= /* CREATE_DEFAULT_ERROR_MODE | */CREATE_SEPARATE_WOW_VDM;
if (mode == _P_DETACH)
flags |= DETACHED_PROCESS;
@@ -649,7 +650,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
cygbench ("spawn-guts");
cygheap->fdtab.set_file_pointers_for_exec ();
- cygheap->user.deimpersonate ();
moreinfo->envp = build_env (envp, envblock, moreinfo->envc, real_path.iscygexec ());
if (!moreinfo->envp || !envblock)
@@ -669,6 +669,9 @@ spawn_guts (const char * prog_arg, const char *const *argv,
effective vs. real ids.
FIXME: If ruid != euid and ruid != saved_uid we currently give
up on ruid. The new process will have ruid == euid. */
+loop:
+ cygheap->user.deimpersonate ();
+
if (!cygheap->user.issetuid ()
|| (cygheap->user.saved_uid == cygheap->user.real_uid
&& cygheap->user.saved_gid == cygheap->user.real_gid
@@ -726,9 +729,6 @@ spawn_guts (const char * prog_arg, const char *const *argv,
if (mode != _P_OVERLAY || !rc)
cygheap->user.reimpersonate ();
- if (envblock)
- free (envblock);
-
/* Set errno now so that debugging messages from it appear before our
final debugging message [this is a general rule for debugging
messages]. */
@@ -776,7 +776,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
strace.execing = 1;
myself.hProcess = hExeced = pi.hProcess;
strcpy (myself->progname, real_path); // FIXME: race?
- close_all_files (true);
+ if (!looped)
+ close_all_files (true);
sigproc_printf ("new process name %s", myself->progname);
/* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
process. So, we need to wait around until the process we've just "execed"
@@ -791,10 +792,13 @@ spawn_guts (const char * prog_arg, const char *const *argv,
dup_proc_pipe essentially a no-op. */
if (!newargv.win16_exe && myself->wr_proc_pipe)
{
- myself->sync_proc_pipe (); /* Make sure that we own wr_proc_pipe
- just in case we've been previously
- execed. */
- myself.zap_cwd ();
+ if (!looped)
+ {
+ myself->sync_proc_pipe (); /* Make sure that we own wr_proc_pipe
+ just in case we've been previously
+ execed. */
+ myself.zap_cwd ();
+ }
myself->dup_proc_pipe (pi.hProcess);
}
pid = myself->pid;
@@ -852,8 +856,16 @@ spawn_guts (const char * prog_arg, const char *const *argv,
{
case _P_OVERLAY:
myself.hProcess = pi.hProcess;
- if (synced && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT
- && !myself->wr_proc_pipe)
+ if (!synced)
+ {
+ if (ch.proc_retry (pi.hProcess) == 0)
+ {
+ looped++;
+ goto loop;
+ }
+ }
+ else if (!myself->wr_proc_pipe
+ && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
{
extern bool is_toplevel_proc;
is_toplevel_proc = true;
@@ -880,6 +892,8 @@ spawn_guts (const char * prog_arg, const char *const *argv,
}
out:
+ if (envblock)
+ free (envblock);
pthread_cleanup_pop (1);
return (int) res;
}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 7589493..3b976c0 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1987,7 +1987,6 @@ setpgid (pid_t pid, pid_t pgid)
if (p->pid != p->pgid)
p->set_has_pgid_children (0);
res = 0;
- // init_console_handler (FALSE);
}
}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 3695f49..73ef0a5 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -302,9 +302,10 @@ bool mmap_is_attached_page (ULONG_PTR);
int winprio_to_nice (DWORD) __attribute__ ((regparm (1)));
DWORD nice_to_winprio (int &) __attribute__ ((regparm (1)));
-bool __stdcall create_pipe (PHANDLE hr, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD)
+bool __stdcall create_pipe (PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD)
__attribute__ ((regparm (3)));
#define CreatePipe create_pipe
+
inline bool flush_file_buffers (HANDLE h)
{
return (GetFileType (h) != FILE_TYPE_PIPE) ? FlushFileBuffers (h) : true;