summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/spawn.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r--winsup/cygwin/spawn.cc159
1 files changed, 90 insertions, 69 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index f23748667..3c12b7057 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -223,13 +223,24 @@ linebuf::prepend (const char *what, int len)
ix = newix;
}
-int __stdcall
+static HANDLE hexec_proc = NULL;
+
+void __stdcall
+exec_fixup_after_fork ()
+{
+ if (hexec_proc)
+ CloseHandle (hexec_proc);
+ hexec_proc = NULL;
+}
+
+static int __stdcall
spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
- const char *const envp[], pinfo *child, int mode)
+ const char *const envp[], int mode)
{
int i;
BOOL rc;
int argc;
+ pid_t cygpid;
hExeced = NULL;
@@ -474,7 +485,7 @@ skip_arg_parsing:
chtype = PROC_EXEC;
}
- init_child_info (chtype, ciresrv, child->pid, spr);
+ init_child_info (chtype, ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
LPBYTE resrv = si.lpReserved2 + sizeof *ciresrv;
# undef ciresrv
@@ -509,6 +520,11 @@ skip_arg_parsing:
if (!hToken && myself->token != INVALID_HANDLE_VALUE)
hToken = myself->token;
+ if (mode == _P_OVERLAY && !hexec_proc &&
+ !DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
+ TRUE, DUPLICATE_SAME_ACCESS))
+ system_printf ("couldn't save current process handle %p, %E", hMainProc);
+
if (hToken)
{
/* allow the child to interact with our window station/desktop */
@@ -549,12 +565,6 @@ skip_arg_parsing:
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (myself->orig_uid);
- /* Set child->uid to USHRT_MAX to force calling internal_getlogin()
- from child process. Clear username and psid to play it safe. */
- child->uid = USHRT_MAX;
- child->username[0] = '\0';
- child->psid = NULL;
-
/* Load users registry hive. */
load_registry_hive (sid);
@@ -599,15 +609,14 @@ skip_arg_parsing:
if (!rc)
__seterrno ();
- MALLOC_CHECK;
- /* Name the handle similarly to proc_subproc. */
- ProtectHandle1 (pi.hProcess, childhProc);
- ProtectHandle (pi.hThread);
- MALLOC_CHECK;
+ if (mode == _P_OVERLAY)
+ cygpid = myself->pid;
+ else
+ cygpid = cygwin_pid (pi.dwProcessId);
/* We print the original program name here so the user can see that too. */
syscall_printf ("%d = spawn_guts (%s, %.132s)",
- rc ? pi.dwProcessId : (unsigned int) -1,
+ rc ? cygpid : (unsigned int) -1,
prog_arg, one_line.buf);
if (!rc)
@@ -617,27 +626,73 @@ skip_arg_parsing:
return -1;
}
- /* Set up child's signal handlers */
- for (i = 0; i < NSIG; i++)
- {
- child->getsig(i).sa_mask = 0;
- if (myself->getsig(i).sa_handler != SIG_IGN || (mode != _P_OVERLAY))
- child->getsig(i).sa_handler = SIG_DFL;
- }
+ MALLOC_CHECK;
+ /* Name the handle similarly to proc_subproc. */
+ ProtectHandle1 (pi.hProcess, childhProc);
+ ProtectHandle (pi.hThread);
+ MALLOC_CHECK;
if (mode == _P_OVERLAY)
{
close_all_files ();
- strcpy (child->progname, real_path_buf);
+ strcpy (myself->progname, real_path_buf);
proc_terminate ();
hExeced = pi.hProcess;
+
+ /* Set up child's signal handlers */
+ /* CGF FIXME - consolidate with signal stuff below */
+ for (i = 0; i < NSIG; i++)
+ {
+ myself->getsig(i).sa_mask = 0;
+ if (myself->getsig(i).sa_handler != SIG_IGN || (mode != _P_OVERLAY))
+ myself->getsig(i).sa_handler = SIG_DFL;
+ }
}
else
{
+ pinfo child (cygpid, 1);
+ if (!child)
+ {
+ set_errno (EAGAIN);
+ syscall_printf ("-1 = spawnve (), process table full");
+ return -1;
+ }
+ child->username[0] = '\0';
+ child->progname[0] = '\0';
+ // CGF FIXME -- need to do this? strcpy (child->progname, path);
+ // CGF FIXME -- need to do this? memcpy (child->username, myself->username, MAX_USER_NAME);
+ child->ppid = myself->pid;
+ child->uid = myself->uid;
+ child->gid = myself->gid;
+ child->pgid = myself->pgid;
+ child->sid = myself->sid;
+ child->ctty = myself->ctty;
+ child->umask = myself->umask;
+ child->process_state |= PID_INITIALIZING;
+ memcpy (child->sidbuf, myself->sidbuf, MAX_SID_LEN);
+ if (myself->psid)
+ child->psid = child->sidbuf;
+ memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
+ memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
+ memcpy (child->root, myself->root, MAX_PATH+1);
+ child->rootlen = myself->rootlen;
child->dwProcessId = pi.dwProcessId;
child->hProcess = pi.hProcess;
child->process_state |= PID_INITIALIZING;
- proc_register (child);
+ for (i = 0; i < NSIG; i++)
+ {
+ child->getsig(i).sa_mask = 0;
+ if (child->getsig(i).sa_handler != SIG_IGN || (mode != _P_OVERLAY))
+ child->getsig(i).sa_handler = SIG_DFL;
+ }
+ if (hToken)
+ {
+ /* Set child->uid to USHRT_MAX to force calling internal_getlogin()
+ from child process. Clear username and psid to play it safe. */
+ child->uid = USHRT_MAX;
+ child->psid = NULL;
+ }
+ child.remember ();
}
sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
@@ -735,13 +790,14 @@ skip_arg_parsing:
* EXIT_REPARENTING status. Wait() syscall in parent will then wait
* for newly created child.
*/
- if (my_parent_is_alive ())
+ pinfo parent (myself->ppid);
+ if (!parent)
+ /* nothing */;
+ else
{
- pinfo *parent = procinfo (myself->ppid);
- sigproc_printf ("parent = %p", parent);
HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
parent->dwProcessId);
- sigproc_printf ("parent's handle = %d", hP);
+ sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId);
if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
res = 1;
else if (hP)
@@ -778,18 +834,11 @@ skip_arg_parsing:
}
if (mode == _P_WAIT)
- {
- waitpid (child->pid, (int *) &res, 0);
- }
+ waitpid (cygpid, (int *) &res, 0);
else if (mode == _P_DETACH)
- {
- /* Lose all memory of this child. */
- res = 0;
- }
+ res = 0; /* Lose all memory of this child. */
else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO))
- {
- res = child->pid;
- }
+ res = cygpid;
return (int) res;
}
@@ -810,7 +859,6 @@ extern "C" int
_spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
const char *const *envp)
{
- pinfo *child;
int ret;
vfork_save *vf = vfork_storage.val ();
@@ -826,7 +874,7 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
case _P_OVERLAY:
/* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
/* Just act as an exec if _P_OVERLAY set. */
- spawn_guts (hToken, path, argv, envp, myself, mode);
+ spawn_guts (hToken, path, argv, envp, mode);
/* Errno should be set by spawn_guts. */
ret = -1;
break;
@@ -834,38 +882,11 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
case _P_NOWAITO:
case _P_WAIT:
case _P_DETACH:
- child = cygwin_shared->p.allocate_pid ();
- if (!child)
- {
- set_errno (EAGAIN);
- syscall_printf ("-1 = spawnve (), process table full");
- return -1;
- }
- strcpy (child->progname, path);
- child->ppid = myself->pid;
- child->uid = myself->uid;
- child->gid = myself->gid;
- child->pgid = myself->pgid;
- child->sid = myself->sid;
- child->ctty = myself->ctty;
- child->umask = myself->umask;
- child->process_state |= PID_INITIALIZING;
- memcpy (child->username, myself->username, MAX_USER_NAME);
- memcpy (child->sidbuf, myself->sidbuf, MAX_SID_LEN);
- if (myself->psid)
- child->psid = child->sidbuf;
- memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
- memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
- memcpy (child->root, myself->root, MAX_PATH+1);
- child->rootlen = myself->rootlen;
subproc_init ();
- ret = spawn_guts (hToken, path, argv, envp, child, mode);
- if (ret == -1)
- child->process_state = PID_NOT_IN_USE;
-
+ ret = spawn_guts (hToken, path, argv, envp, mode);
if (vf)
{
- vf->pid = child->pid;
+ vf->pid = ret;
longjmp (vf->j, 1);
}
break;