summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/spawn.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2000-07-29 16:24:59 +0000
committerChristopher Faylor <me@cgf.cx>2000-07-29 16:24:59 +0000
commit84c7d4093270dc07de4531ab6648a12daaff77c3 (patch)
tree067ed4cf0bffd057a63b2f472bcab39854f86c17 /winsup/cygwin/spawn.cc
parent53211514a0466b7e29f6f53c11b769befddfdfa6 (diff)
downloadcygnal-84c7d4093270dc07de4531ab6648a12daaff77c3.tar.gz
cygnal-84c7d4093270dc07de4531ab6648a12daaff77c3.tar.bz2
cygnal-84c7d4093270dc07de4531ab6648a12daaff77c3.zip
* include/cygwin/version.h: Bump DLL minor version number to 5 due to all of
the changes below. Redefine process structure to avoid a fixed size table. Redefine pinfo/_pinfo classes. Use these throughout. * dcrt0.cc (dll_crt0_1): Accomodate set_myself argument change. (__api_fatal): Accomodate _pinfo::record_death argument change. * exceptions.cc (really_exit): Ditto. (sig_handle_tty_stop): Use pinfo constructor to access process info. (events_init): Don't create pinfo_mutex since it is no longer required. * external.cc (fillout_pinfo): Use winpids class to iterate over all system pids. (cygwin_internal): lock_pinfo_for_update and unlock_pinfo are now noops. * fhandler_termios.cc (fhandler_termios::set_ctty): Use pinfo constructor to access process info. * fork.cc (fork): Reorganize to initialize child info after the child has started since that is when we know the child's winpid, which is necessary to allocate the pinfo shared memory. * mmap.cc (recreate_mmaps_after_fork): Change arg type to _pinfo. * pinfo.cc: Rename pinfo methods to _pinfo throughout. Eliminate pinfo_list stuff. (set_myself): Accept a pid argument now. Call pinfo initializer to initialize myself. Detect when this is an "execed" process and create an "indirect" pid block. (pinfo_init): Accomodate set_myself arg change. (procinfo): Remove. (pinfo::lock_pinfo): Remove. (pinfo::unlock_pinfo): Remove. (pinfo::init): New method. Allocates shared memory space for process pinfo structure. (pinfo::record_death): Don't call locking functions. (cygwin_winpid_to_pid): Simplify by using new pinfo constructor. (EnumProcessesW95): New function for iterating over processes on Windows 95. (winpids::winpids): New constructor for winpids class. Sets up a list of process ids. (enum_init): Initialize w95/wnt pid enumerators. * shared.cc (shared-info::initialize): Remove pid initialization. * shared.h: Move pinfo stuff into pinfo.h. (class shared_info): Remove pinfo_list element. * signal.cc (kill_worker): Use pinfo constructor to access process info. (kill_pgrp): Ditto. Use winpids methods to access list of processes. * sigproc.cc: Throughout, modify to use _pinfo where appropriate. (proc_exists (pid_t)): New function. Determines if a process exists based on the pid. (proc_exists (_pinfo *p): Use new proc_exists function above. (proc_subproc): Copy pinfo stuff around rather than _pinfo pointers. Try to be careful about releasing shared memory when we don't need it anymore. Remove pinfo locks. (remove_zombies): Remove pinfo memory when zombie is going away. * sigproc.h: Reflect _pinfo/pinfo changes in sigproc.cc. * spawn.cc (spawn_guts): Eliminate pinfo *child argument. Reorganize to only initialize child pinfo after process has been started and we know the windows pid. (_spawnve): Reflect spawn_guts changes. * syscalls.cc (setpgid): Use pinfo constructor to access process info. (getpgid): Ditto. (internal_getlogin): Use _pinfo. * winsup.h: Eliminate pinfo_mutex. Eliminate spawn_guts declaration since it is static now. Reflect set_myself argument change. * include/sys/cygwin.h: Add some PID_* enums to accomodate new pinfo stuff. * include/cygwin/version.h: Update minor version for cygdrive changes below.
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;