diff options
author | Christopher Faylor <me@cgf.cx> | 2006-03-18 19:17:21 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2006-03-18 19:17:21 +0000 |
commit | a939686807dd8e832939fddf514040fdba7077d8 (patch) | |
tree | e9e816e39dde05a3353c9137c9763f6d474adac9 /winsup/cygwin/spawn.cc | |
parent | 61337a0f4594e1301011b775a6f9672fc58b4ec0 (diff) | |
download | cygnal-a939686807dd8e832939fddf514040fdba7077d8.tar.gz cygnal-a939686807dd8e832939fddf514040fdba7077d8.tar.bz2 cygnal-a939686807dd8e832939fddf514040fdba7077d8.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r-- | winsup/cygwin/spawn.cc | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index cac02d988..16955bbb7 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; } |