diff options
author | Christopher Faylor <me@cgf.cx> | 2000-07-29 20:24:59 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-07-29 20:24:59 +0400 |
commit | 84c7d4093270dc07de4531ab6648a12daaff77c3 (patch) | |
tree | 067ed4cf0bffd057a63b2f472bcab39854f86c17 /winsup/cygwin | |
parent | 53211514a0466b7e29f6f53c11b769befddfdfa6 (diff) |
* 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')
29 files changed, 761 insertions, 633 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 310f90500..e1e7020c9 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,77 @@ +Sat Jul 29 12:11:33 2000 Christopher Faylor <cgf@cygnus.com> + + * include/cygwin/version.h: Bump DLL minor version number to 5 due + to all of the changes below. + +Sat Jul 29 12:01:32 2000 Christopher Faylor <cgf@cygnus.com> + + 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. + +Sat Jul 29 12:13:27 2000 Christopher Faylor <cgf@cygnus.com> + + * include/cygwin/version.h: Update minor version for cygdrive changes + below. + Sat Jul 29 11:59:29 2000 Christopher Faylor <cgf@cygnus.com> * environ.cc (parse_thing): Make binmode a DWORD. @@ -5,6 +79,16 @@ Sat Jul 29 11:59:29 2000 Christopher Faylor <cgf@cygnus.com> determine default open mode. * winsup.h: Declare binmode. +Sat Jul 29 00:16:35 2000 Christopher Faylor <cgf@cygnus.com> + + * include/cygwin/cygwin_dll.h: Update for modern compilers. + * lib/cygwin_crt0.c: Inexplicably need to define alloca for newer + compilers. + * fhandler.h (fhandler_console): Add new method. + * fhandler.cc (fhandler_console::set_cursor_maybe): New method. + (fhandler_console::read): Set cursor if it has moved to make it + visible. + Thu Jul 27 22:54:28 2000 Jason Tishler <jt@dothill.com> * dcrt0.cc (dummy_autoload): Add load statement for RegDeleteValueA. diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 5c9139ccf..31675836b 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -8,7 +8,7 @@ __infinity __main __srget __swbuf -__vc__10pinfo_listi +; __vc__10pinfo_listi @ALLOCA@ cygwin_stackdump abort diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 8a5240606..43385287d 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -657,7 +657,7 @@ dll_crt0_1 () // should be blocked. if (mypid) - set_myself (cygwin_shared->p[mypid]); + set_myself ((pid_t) mypid); (void) SetErrorMode (SEM_FAILCRITICALERRORS); @@ -1047,7 +1047,7 @@ __api_fatal (const char *fmt, ...) /* We are going down without mercy. Make sure we reset our process_state. */ sigproc_terminate (); - myself->record_death (FALSE); + myself->record_death (); #ifdef DEBUGGING (void) try_to_debug (); #endif diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index f9785bcd4..d834160a9 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -627,7 +627,7 @@ winenv (const char * const *envp, int keep_posix) did not seem to know about importing data variables from the DLL. So, we have to synchronize cygwin's idea of the environment with the main program's with each reference to the environment. */ -char ** __stdcall +extern "C" char ** __stdcall cur_environ () { if (*main_environ != __cygwin_environ) diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 22f262cc8..c6cad810c 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -315,7 +315,6 @@ try_to_debug () /* if any of these mutexes is owned, we will fail to start any cygwin app until trapped app exits */ - ReleaseMutex (pinfo_mutex); ReleaseMutex (title_mutex); /* prevent recursive exception handling */ @@ -877,7 +876,7 @@ sig_handle_tty_stop (int sig) */ if (my_parent_is_alive ()) { - pinfo *parent = procinfo (myself->ppid); + pinfo parent (myself->ppid); sig_send (parent, __SIGCHILDSTOPPED); } sigproc_printf ("process %d stopped by signal %d, parent_alive %p", @@ -1007,27 +1006,18 @@ signal_exit (int rc) if (exit_already++) { /* We are going down - reset our process_state without locking. */ - myself->record_death (FALSE); + myself->record_death (); ExitProcess (rc); } do_exit (rc); } -HANDLE NO_COPY pinfo_mutex = NULL; HANDLE NO_COPY title_mutex = NULL; void events_init (void) { - /* pinfo_mutex protects access to process table */ - - if (!(pinfo_mutex = CreateMutex (&sec_all_nih, FALSE, - shared_name ("pinfo_mutex", 0)))) - api_fatal ("catastrophic failure - unable to create pinfo_mutex, %E"); - - ProtectHandle (pinfo_mutex); - /* title_mutex protects modification of console title. It's neccessary while finding console window handle */ @@ -1056,12 +1046,11 @@ events_init (void) void events_terminate (void) { -//CloseHandle (pinfo_mutex); // Use implicit close on exit to avoid race ForceCloseHandle (title_mutex); exit_already = 1; } -#define pid_offset (unsigned)(((pinfo *)NULL)->pid) +#define pid_offset (unsigned)(((_pinfo *)NULL)->pid) extern "C" { static void __stdcall reset_signal_arrived () __attribute__ ((unused)); diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index f187d9779..f31d34938 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -13,53 +13,80 @@ details. */ #include "winsup.h" static external_pinfo * -fillout_pinfo (DWORD pid) +fillout_pinfo (pid_t pid, int winpid) { BOOL nextpid; - pinfo *p = NULL; - int i; static external_pinfo ep; if ((nextpid = !!(pid & CW_NEXTPID))) pid ^= CW_NEXTPID; - for (i = 0; i < cygwin_shared->p.size(); i++, p = NULL) + + static winpids pids (0); + + if (!pids.npids) + pids.init (); + + memset (&ep, 0, sizeof ep); + for (unsigned i = 0; i < pids.npids; i++) { - p = cygwin_shared->p.vec + i; - if (!pid || (DWORD) p->pid == pid) + if (!pids[i]) + continue; + pinfo p (pids[i]); + pid_t thispid; + + if (p) + thispid = p->pid; + else if (winpid) + thispid = pids[i]; + else + continue; + + if (!pid || thispid == pid) { if (nextpid && pid) { pid = 0; nextpid = 0; + continue; + } + + if (!p) + { + ep.pid = pids[i]; + ep.dwProcessId = cygwin_pid (pids[i]); + ep.process_state = PID_IN_USE; + ep.ctty = -1; } else if (p->pid && NOTSTATE(p, PID_CLEAR)) - break; + { + ep.ctty = tty_attached (p) ? p->ctty : -1; + ep.pid = p->pid; + ep.ppid = p->ppid; + ep.hProcess = p->hProcess; + ep.dwProcessId = p->dwProcessId; + ep.uid = p->uid; + ep.gid = p->gid; + ep.pgid = p->pgid; + ep.sid = p->sid; + ep.umask = p->umask; + ep.start_time = p->start_time; + ep.rusage_self = p->rusage_self; + ep.rusage_children = p->rusage_children; + strcpy (ep.progname, p->progname); + ep.strace_mask = 0; + ep.strace_file = 0; + + ep.process_state = p->process_state; + } + break; } } - if (p == NULL) - return 0; - - memset (&ep, 0, sizeof ep); - ep.ctty = tty_attached (p) ? p->ctty : -1; - ep.pid = p->pid; - ep.ppid = p->ppid; - ep.hProcess = p->hProcess; - ep.dwProcessId = p->dwProcessId; -//ep.dwSpawnedProcessId = p->dwSpawnedProcessId; - ep.uid = p->uid; - ep.gid = p->gid; - ep.pgid = p->pgid; - ep.sid = p->sid; - ep.umask = p->umask; - ep.start_time = p->start_time; - ep.rusage_self = p->rusage_self; - ep.rusage_children = p->rusage_children; - strcpy (ep.progname, p->progname); - ep.strace_mask = 0; - ep.strace_file = 0; - - ep.process_state = p->process_state; + if (!ep.pid) + { + pids.reset (); + return 0; + } return &ep; } @@ -80,11 +107,9 @@ cygwin_internal (cygwin_getinfo_types t, ...) switch (t) { case CW_LOCK_PINFO: - return lock_pinfo_for_update (va_arg (arg, DWORD)); - break; + return 1; case CW_UNLOCK_PINFO: - unlock_pinfo (); return 1; case CW_GETTHREADNAME: @@ -98,7 +123,7 @@ cygwin_internal (cygwin_getinfo_types t, ...) } case CW_GETPINFO: - return (DWORD) fillout_pinfo (va_arg (arg, DWORD)); + return (DWORD) fillout_pinfo (va_arg (arg, DWORD), 0); case CW_GETVERSIONINFO: return (DWORD) cygwin_version_strings; @@ -122,6 +147,9 @@ cygwin_internal (cygwin_getinfo_types t, ...) return get_cygdrive_prefixes (user, system); } + case CW_GETPINFO_FULL: + return (DWORD) fillout_pinfo (va_arg (arg, pid_t), 1); + default: return (DWORD) -1; } diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index bd58c3a12..7e266ab8d 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -110,6 +110,23 @@ set_console_state_for_spawn () return 1; } +void +fhandler_console::set_cursor_maybe () +{ + CONSOLE_SCREEN_BUFFER_INFO now; + static CONSOLE_SCREEN_BUFFER_INFO last = {{0, 0}, {-1, -1}, 0, {0, 0}, {0, 0}}; + + if (!GetConsoleScreenBufferInfo (get_output_handle(), &now)) + return; + + if (last.dwCursorPosition.X != now.dwCursorPosition.X || + last.dwCursorPosition.Y != now.dwCursorPosition.Y) + { + SetConsoleCursorPosition (get_output_handle (), now.dwCursorPosition); + last.dwCursorPosition = now.dwCursorPosition; + } +} + int fhandler_console::read (void *pv, size_t buflen) { @@ -147,7 +164,7 @@ fhandler_console::read (void *pv, size_t buflen) if ((bgres = bg_check (SIGTTIN)) <= 0) return bgres; - cursor_rel (0,0); /* to make cursor appear on the screen immediately */ + set_cursor_maybe (); /* to make cursor appear on the screen immediately */ switch (WaitForMultipleObjects (nwait, w4, FALSE, INFINITE)) { case WAIT_OBJECT_0: @@ -1244,6 +1261,7 @@ fhandler_console::write (const void *vsrc, size_t len) break; } } + syscall_printf ("%d = write_console (,..%d)", len, len); return len; diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index 6036cd66c..d5213c3f2 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -84,7 +84,7 @@ fhandler_termios::set_ctty (int ttynum, int flags) syscall_printf ("attached tty%d sid %d, pid %d, tty->pgid %d, tty->sid %d", ttynum, myself->sid, myself->pid, tc->pgid, tc->getsid ()); - pinfo *p = procinfo (tc->getsid ()); + pinfo p (tc->getsid ()); if (myself->sid == myself->pid && (p == myself || !proc_exists (p))) { @@ -127,7 +127,7 @@ fhandler_termios::bg_check (int sig) /* If the process group is no more or if process is ignoring or blocks 'sig', return with error */ - int pgid_gone = !proc_exists (procinfo (myself->pgid)); + int pgid_gone = !proc_exists (myself->pgid); int sigs_ignored = ((void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN) || (myself->getsigmask () & SIGTOMASK (sig)); diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index e585fad36..06cd1ff65 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -241,11 +241,11 @@ fork () int res; DWORD rc; HANDLE hParent; - pinfo *child; HANDLE subproc_ready, forker_finished; void *stack_here; int x; PROCESS_INFORMATION pi = {0, NULL, 0, 0}; + static NO_COPY HANDLE last_fork_proc = NULL; MALLOC_CHECK; @@ -271,15 +271,6 @@ fork () return -1; } - /* Don't start the fork until we have the lock. */ - child = cygwin_shared->p.allocate_pid (); - if (!child) - { - set_errno (EAGAIN); - syscall_printf ("-1 = fork (), process table full"); - return -1; - } - /* Remember the address of the first loaded dll and decide if we need to load dlls. We do this here so that this information will be available in the parent and, when @@ -292,12 +283,9 @@ fork () if (x == 0) { - /* This will help some of the confusion. */ fflush (stdout); - debug_printf ("parent pid %d, child pid %d", myself->pid, child->pid); - subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL); forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL); ProtectHandle (subproc_ready); @@ -326,7 +314,7 @@ fork () free (malloc (4096)); #endif - init_child_info (PROC_FORK1, &ch, child->pid, subproc_ready); + init_child_info (PROC_FORK1, &ch, 1, subproc_ready); ch.forker_finished = forker_finished; ch.heaptop = user_data->heaptop; @@ -335,10 +323,6 @@ fork () stack_base (ch); - /* Initialize things that are done later in dll_crt0_1 that aren't done - for the forkee. */ - strcpy(child->progname, myself->progname); - STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}; si.cb = sizeof (STARTUPINFO); @@ -393,7 +377,6 @@ fork () { __seterrno (); syscall_printf ("-1 = fork(), CreateProcessA failed"); - child->process_state = PID_NOT_IN_USE; ForceCloseHandle(subproc_ready); ForceCloseHandle(forker_finished); subproc_ready = forker_finished = NULL; @@ -403,6 +386,12 @@ fork () return -1; } + pinfo forked (cygwin_pid (pi.dwProcessId), 1); + + /* Initialize things that are done later in dll_crt0_1 that aren't done + for the forkee. */ + strcpy(forked->progname, myself->progname); + /* Restore impersonation */ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) seteuid (uid); @@ -411,35 +400,43 @@ fork () /* Protect the handle but name it similarly to the way it will be called in subproc handling. */ ProtectHandle1 (pi.hProcess, childhProc); + if (os_being_run != winNT) + { + if (last_fork_proc) + CloseHandle (last_fork_proc); + if (!DuplicateHandle (hMainProc, pi.hProcess, hMainProc, &last_fork_proc, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + system_printf ("couldn't create last_fork_proc, %E"); + } /* Fill in fields in the child's process table entry. */ - child->ppid = myself->pid; - child->hProcess = pi.hProcess; - child->dwProcessId = pi.dwProcessId; - 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->copysigs(myself); - child->process_state |= PID_INITIALIZING | + forked->ppid = myself->pid; + forked->hProcess = pi.hProcess; + forked->dwProcessId = pi.dwProcessId; + forked->uid = myself->uid; + forked->gid = myself->gid; + forked->pgid = myself->pgid; + forked->sid = myself->sid; + forked->ctty = myself->ctty; + forked->umask = myself->umask; + forked->copysigs(myself); + forked->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY); - memcpy (child->username, myself->username, MAX_USER_NAME); - memcpy (child->sidbuf, myself->sidbuf, MAX_SID_LEN); + memcpy (forked->username, myself->username, MAX_USER_NAME); + memcpy (forked->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); - child->token = myself->token; - child->impersonated = myself->impersonated; - child->orig_uid = myself->orig_uid; - child->orig_gid = myself->orig_gid; - child->real_uid = myself->real_uid; - child->real_gid = myself->real_gid; - memcpy (child->root, myself->root, MAX_PATH+1); - child->rootlen = myself->rootlen; - set_child_mmap_ptr (child); + forked->psid = forked->sidbuf; + memcpy (forked->logsrv, myself->logsrv, MAX_HOST_NAME); + memcpy (forked->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1); + forked->token = myself->token; + forked->impersonated = myself->impersonated; + forked->orig_uid = myself->orig_uid; + forked->orig_gid = myself->orig_gid; + forked->real_uid = myself->real_uid; + forked->real_gid = myself->real_gid; + strcpy (forked->root, myself->root); + forked->rootlen = myself->rootlen; + set_child_mmap_ptr (forked); /* Wait for subproc to initialize itself. */ if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp")) @@ -476,7 +473,7 @@ fork () goto cleanup; } - proc_register (child); + forked.remember (); /* Start thread, and wait for it to reload dlls. */ if (!resume_child (pi, forker_finished) || @@ -508,7 +505,7 @@ fork () forker_finished = NULL; pi.hThread = NULL; - res = child->pid; + res = forked->pid; } else { @@ -518,8 +515,7 @@ fork () (void) stack_dummy (0); // Just to make sure debug_printf ("child is running %d", x); - debug_printf ("self %p, pid %d, ppid %d", - myself, x, myself ? myself->ppid : -1); + debug_printf ("pid %d, ppid %d", x, myself->ppid); /* Restore the inheritance state as in parent Don't call setuid here! The flags are already set. */ @@ -563,6 +559,7 @@ fork () dtable.fixup_after_fork (hParent); signal_fixup_after_fork (); + exec_fixup_after_fork (); MALLOC_CHECK; @@ -605,7 +602,6 @@ fork () /* Common cleanup code for failure cases */ cleanup: /* Remember to de-allocate the fd table. */ - child->process_state = PID_NOT_IN_USE; if (pi.hProcess) ForceCloseHandle1 (pi.hProcess, childhProc); if (pi.hThread) @@ -614,7 +610,7 @@ cleanup: ForceCloseHandle (subproc_ready); if (forker_finished) ForceCloseHandle (forker_finished); - forker_finished = subproc_ready = child->hProcess = NULL; + forker_finished = subproc_ready = NULL; return -1; } diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 2e1b898c4..6f9bb11a6 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -44,7 +44,7 @@ details. */ /* The current cygwin version is 1.1.0 */ #define CYGWIN_VERSION_DLL_MAJOR 1001 -#define CYGWIN_VERSION_DLL_MINOR 4 +#define CYGWIN_VERSION_DLL_MINOR 5 /* Major numbers before CYGWIN_VERSION_DLL_EPOCH are incompatible. */ @@ -115,10 +115,12 @@ details. */ with crt0 startup code. 24: Export poll and _poll. 25: Export getmode and _getmode. + 26: CW_GET_CYGDRIVE_PREFIXES addition to external.cc + 27: CW_GETPINFO_FULL addition to external.cc */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 24 +#define CYGWIN_VERSION_API_MINOR 28 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index 978e976d5..8d7b5d433 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -60,7 +60,8 @@ typedef enum CW_READ_V1_MOUNT_TABLES, CW_USER_DATA, CW_PERFILE, - CW_GET_CYGDRIVE_PREFIXES + CW_GET_CYGDRIVE_PREFIXES, + CW_GETPINFO_FULL } cygwin_getinfo_types; #define CW_NEXTPID 0x80000000 // or with pid to get next one @@ -86,7 +87,9 @@ enum PID_USETTY = 0x1000, // Setting this enables or disables cygwin's // tty support. This is inherited by // all execed or forked processes. - PID_REPARENT = 0x2000 // child has execed + PID_REPARENT = 0x2000, // child has execed + PID_EXECED = 0x4000, // redirect to original pid info block + PID_NOREDIR = 0x8000 // don't redirect if execed }; #ifdef WINVER diff --git a/winsup/cygwin/mkvers.sh b/winsup/cygwin/mkvers.sh index 84cb87d31..da9688a51 100755 --- a/winsup/cygwin/mkvers.sh +++ b/winsup/cygwin/mkvers.sh @@ -172,4 +172,5 @@ fi echo "Version $cygwin_ver" set -$- $builddate +set -x exec $windres --include-dir $dir/../w32api/include --include-dir $dir/include --define CYGWIN_BUILD_DATE="$1" --define CYGWIN_BUILD_TIME="$2" --define CYGWIN_VERSION='"'"$cygwin_ver"'"' $rcfile winver.o diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index b63787ed4..9cbf5005d 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -468,7 +468,7 @@ recreate_mmaps_after_fork (void *param) pointer for fork. */ void __stdcall -set_child_mmap_ptr (pinfo *child) +set_child_mmap_ptr (_pinfo *child) { child->mmap_ptr = (void *) mmapped_areas; } diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index bc26b4cf1..afb09d822 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -16,11 +16,12 @@ details. */ #include <sys/socket.h> #include <sys/un.h> +#include <unistd.h> + #define Win32_Winsock #include "winsup.h" #include <netdb.h> #include <fcntl.h> -#include <unistd.h> #include "autoload.h" #include <winsock.h> diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc index 278eb771f..cf0a1595e 100644 --- a/winsup/cygwin/ntea.cc +++ b/winsup/cygwin/ntea.cc @@ -13,7 +13,6 @@ details. */ #include <winsup.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> /* Default to not using NTEA information */ BOOL allow_ntea = FALSE; diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index d6ab35aa8..e2956ee89 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -14,33 +14,27 @@ details. */ #include <limits.h> #include "winsup.h" -/* The first pid used; also the lowest value allowed. */ -#define PBASE 1000 - static char NO_COPY pinfo_dummy[sizeof(pinfo)] = {0}; -pinfo NO_COPY *myself = (pinfo *)&pinfo_dummy; // Avoid myself != NULL checks +pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks +static pinfo NO_COPY myself_identity ((_pinfo *)&pinfo_dummy); /* Initialize the process table. This is done once when the dll is first loaded. */ -void -pinfo_list::init (void) -{ - next_pid = PBASE; /* Next pid to try to allocate. */ - - /* We assume the shared data area is already initialized to zeros. - Note that SIG_DFL is zero. */ -} - -pinfo * __stdcall -set_myself (pinfo *p) +void __stdcall +set_myself (pid_t pid) { - myself = p; - if (!p) - return NULL; - + DWORD winpid = GetCurrentProcessId (); + if (pid == 1) + pid = cygwin_pid (winpid); + myself.init (pid, 1); + myself->dwProcessId = winpid; + myself->process_state |= PID_IN_USE; myself->start_time = time (NULL); /* Register our starting time. */ + pid_t myself_cyg_pid = cygwin_pid (myself->dwProcessId); + if (pid != myself_cyg_pid) + myself_identity.init (myself_cyg_pid, PID_EXECED); char buf[30]; __small_sprintf (buf, "cYg%8x %x", _STRACE_INTERFACE_ACTIVATE_ADDR, @@ -65,7 +59,7 @@ set_myself (pinfo *p) strace.prntf (1, "**********************************************"); } - return myself; + return; } /* Initialize the process table entry for the current task. @@ -94,9 +88,9 @@ pinfo_init (LPBYTE info) { /* Invent our own pid. */ - if (!set_myself (cygwin_shared->p.allocate_pid ())) - api_fatal ("No more processes"); - myself->ppid = myself->pgid = myself->sid = myself->pid; + set_myself (1); + myself->ppid = 1; + myself->pgid = myself->sid = myself->pid; myself->ctty = -1; myself->uid = USHRT_MAX; @@ -106,25 +100,8 @@ pinfo_init (LPBYTE info) debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid); } -/* [] operator. This is the mechanism for table lookups. */ -/* Returns the index into the pinfo_list table for pid arg */ - -pinfo * -pinfo_list::operator[] (pid_t pid) -{ - if (pid <= 0) - return NULL; - - pinfo *p = vec + (pid % size ()); - - if (p->pid != pid || p->process_state == PID_NOT_IN_USE) - return NULL; - else - return p; -} - struct sigaction& -pinfo::getsig(int sig) +_pinfo::getsig(int sig) { #ifdef _MT_SAFE if ( thread2signal ) @@ -136,7 +113,7 @@ pinfo::getsig(int sig) }; sigset_t& -pinfo::getsigmask () +_pinfo::getsigmask () { #ifdef _MT_SAFE if ( thread2signal ) @@ -148,7 +125,7 @@ pinfo::getsigmask () }; void -pinfo::setsigmask (sigset_t _mask) +_pinfo::setsigmask (sigset_t _mask) { #ifdef _MT_SAFE if ( thread2signal ) @@ -160,7 +137,7 @@ pinfo::setsigmask (sigset_t _mask) } LONG * -pinfo::getsigtodo(int sig) +_pinfo::getsigtodo(int sig) { #ifdef _MT_SAFE if ( thread2signal ) @@ -174,7 +151,7 @@ pinfo::getsigtodo(int sig) extern HANDLE hMainThread; HANDLE -pinfo::getthread2signal() +_pinfo::getthread2signal() { #ifdef _MT_SAFE if ( thread2signal ) @@ -186,7 +163,7 @@ pinfo::getthread2signal() } void -pinfo::setthread2signal(void *_thr) +_pinfo::setthread2signal(void *_thr) { #ifdef _MT_SAFE // assert has myself lock @@ -196,190 +173,87 @@ pinfo::setthread2signal(void *_thr) } void -pinfo::copysigs(pinfo *_other) +_pinfo::copysigs(_pinfo *_other) { sigs = _other->sigs; } -pinfo * __stdcall -procinfo (int pid) -{ - return cygwin_shared->p[pid]; -} - -#ifdef DEBUGGING -/* - * Code to lock/unlock the process table. - */ - -int __stdcall -lpfu (const char *func, int ln, DWORD timeout) +void +_pinfo::record_death () { - int rc; - DWORD t; - - debug_printf ("timeout %d, pinfo_mutex %p", timeout, pinfo_mutex); - t = (timeout == INFINITE) ? 10000 : timeout; - SetLastError(0); - while ((rc = WaitForSingleObject (pinfo_mutex, t)) != WAIT_OBJECT_0) + /* CGF FIXME - needed? */ + if (dwProcessId == GetCurrentProcessId () && !my_parent_is_alive ()) { - if (rc == WAIT_ABANDONED_0) - break; - system_printf ("%s:%d having problems getting lock", func, ln); - system_printf ("*** %s, rc %d, %E", cygwin_shared->p.lock_info, rc); - if (t == timeout) - break; - } - - __small_sprintf (cygwin_shared->p.lock_info, "%s(%d), pid %d ", func, ln, - (user_data && myself) ? (int)myself->dwProcessId : -1); - return rc; + process_state = PID_NOT_IN_USE; + hProcess = NULL; + } } void -unlock_pinfo (void) +pinfo::init (pid_t n, DWORD create) { + if (n == myself->pid) + { + child = myself; + destroy = 0; + h = NULL; + return; + } - debug_printf ("handle %d", pinfo_mutex); + int created; + char mapname[MAX_PATH]; + __small_sprintf (mapname, "cygpid.%x", n); - if (!cygwin_shared->p.lock_info[0]) - system_printf ("lock_info not set?"); + int mapsize; + if (create & PID_EXECED) + mapsize = PINFO_REDIR_SIZE; else - strcat (cygwin_shared->p.lock_info, " unlocked"); - if (!ReleaseMutex (pinfo_mutex)) - system_printf ("ReleaseMutext (pinfo_mutex<%p>) failed, %E", pinfo_mutex); -} -#else -/* - * Code to lock/unlock the process table. - */ - -int __stdcall -lock_pinfo_for_update (DWORD timeout) -{ - DWORD rc; - DWORD t; + mapsize = sizeof (_pinfo); - debug_printf ("timeout %d, pinfo_mutex %p", timeout, pinfo_mutex); - t = (timeout == INFINITE) ? 10000 : timeout; - SetLastError(0); - while ((rc = WaitForSingleObject (pinfo_mutex, t)) != WAIT_OBJECT_0) + if (!create) { - if (rc == WAIT_ABANDONED_0) - break; - system_printf ("rc %d, pinfo_mutex %p, %E", pinfo_mutex, rc); - if (t == timeout) - break; - if (rc == WAIT_FAILED) - /* sigh, must be properly fixed up later. */ - return rc; - Sleep(10); /* to prevent 100% CPU in those rare cases */ - } - - return (int)rc; -} - -void -unlock_pinfo (void) -{ - - debug_printf ("handle %d", pinfo_mutex); - - ReleaseMutex (pinfo_mutex); -} -#endif - - -/* Allocate a process table entry by finding an empty slot in the - fixed-size process table. We could use a linked list, but this - would probably be too slow. - - Try to allocate next_pid, incrementing next_pid and trying again - up to size() times at which point we reach the conclusion that - table is full. Eventually at this point we would grow the table - by size() and start over. If we find a pid to use, - - If all else fails, sweep through the loop looking for processes that - may have died abnormally without registering themselves as "dead". - Clear out these pinfo structures. Then scan the table again. - - Note that the process table is in the shared data space and thus - is susceptible to corruption. The amount of time spent scanning the - table is presumably quite small compared with the total time to - create a process. -*/ - -pinfo * -pinfo_list::allocate_pid (void) -{ - - pinfo *newp; - - lock_pinfo_for_update (INFINITE); - for (int tries = 0; ; tries++) + /* CGF FIXME -- deal with inheritance after an exec */ + h = OpenFileMappingA (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapname); + created = 0; + } + else { - for (int i = next_pid; i < (next_pid + size ()); i++) - { - /* i mod size() gives place to check */ - newp = vec + (i % size()); - if (newp->process_state == PID_NOT_IN_USE) - { - debug_printf ("found empty slot %d for pid %d", - (i % size ()), i); - next_pid = i; - goto gotit; - } - } - - if (tries > 0) - break; - - /* try once to remove bogus dead processes */ - debug_printf ("clearing out deadwood"); - for (newp = vec; newp < vec + size(); newp++) - proc_exists (newp); + h = CreateFileMapping ((HANDLE) 0xffffffff, &sec_none_nih, + PAGE_READWRITE, 0, mapsize, mapname); + created = h && GetLastError () != ERROR_ALREADY_EXISTS; } - /* The process table is full. */ - debug_printf ("process table is full"); - unlock_pinfo (); - - return NULL; - -gotit: - - /* Set new pid based on the position of this element in the pinfo list */ - newp->pid = next_pid; - - /* Determine next slot to consider, wrapping if we hit the end of - * the array. Since allocation involves looping through size () pids, - * don't allow next_pid to be greater than SHRT_MAX - size (). - */ - if (next_pid < (SHRT_MAX - size ())) - next_pid++; - else - next_pid = PBASE; + if (!h) + { + if (create) + __seterrno (); + child = NULL; + return; + } - newp->process_state = PID_IN_USE; - unlock_pinfo (); + child = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - memset (newp, 0, PINFO_ZERO); - debug_printf ("pid %d, state %x", newp->pid, newp->process_state); - return newp; -} + if (child->process_state & PID_EXECED) + { + pid_t realpid = child->pid; + release (); + if (realpid == n) + api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n); + return init (realpid); + } -void -pinfo::record_death (int lock) -{ - int unlock = lock ? 0 : lock_pinfo_for_update (999); - if (dwProcessId == GetCurrentProcessId () && !my_parent_is_alive ()) + if (created) { - process_state = PID_NOT_IN_USE; - hProcess = NULL; + if (!(create & PID_EXECED)) + child->pid = n; + else + { + child->pid = myself->pid; + child->process_state |= PID_IN_USE | PID_EXECED; + } } - if (unlock) - unlock_pinfo (); + destroy = 1; } /* DOCTOOL-START @@ -412,18 +286,92 @@ a cygwin pid.</para> extern "C" pid_t cygwin_winpid_to_pid (int winpid) { - for (int i = 0; i < cygwin_shared->p.size (); i++) - { - pinfo *p = &cygwin_shared->p.vec[i]; + pinfo p (winpid); + if (p) + return p->pid; - if (p->process_state == PID_NOT_IN_USE) - continue; + set_errno (ESRCH); + return (pid_t) -1; +} + +#include <tlhelp32.h> +#include <psapi.h> + +typedef BOOL (WINAPI * ENUMPROCESSES) (DWORD *, DWORD, DWORD *); +typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD, DWORD); +typedef BOOL (WINAPI * PROCESSWALK) (HANDLE, LPPROCESSENTRY32); +typedef BOOL (WINAPI * CLOSESNAPSHOT) (HANDLE); + +static NO_COPY CREATESNAPSHOT myCreateToolhelp32Snapshot = NULL; +static NO_COPY PROCESSWALK myProcess32First = NULL; +static NO_COPY PROCESSWALK myProcess32Next = NULL; +static BOOL WINAPI enum_init (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded); - /* FIXME: signed vs unsigned comparison: winpid can be < 0 !!! */ - if (p->dwProcessId == (DWORD)winpid) - return p->pid; +static NO_COPY ENUMPROCESSES myEnumProcesses = enum_init; + +static BOOL WINAPI +EnumProcessesW95 (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded) +{ + HANDLE h; + + *cbneeded = 0; + h = myCreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); + if (!h) + return 0; + + PROCESSENTRY32 proc; + int i = 0; + proc.dwSize = sizeof (proc); + if (myProcess32First(h, &proc)) + do + lpidProcess[i++] = cygwin_pid (proc.th32ProcessID); + while (myProcess32Next (h, &proc)); + CloseHandle (h); + if (i == 0) + return 0; + *cbneeded = i * sizeof (DWORD); + return 1; +} + +void +winpids::init () +{ + DWORD n; + if (!myEnumProcesses (pidlist, sizeof (pidlist) / sizeof (pidlist[0]), &n)) + npids = 0; + else + npids = n / sizeof (pidlist[0]); + + pidlist[npids] = 0; +} + +static BOOL WINAPI +enum_init (DWORD *lpidProcess, DWORD cb, DWORD *cbneeded) +{ + HINSTANCE h; + if (os_being_run == winNT) + { + h = LoadLibrary ("psapi.dll"); + if (!h) + return 0; + myEnumProcesses = (ENUMPROCESSES) GetProcAddress (h, "EnumProcesses"); + if (!myEnumProcesses) + return 0; + } + else + { + h = GetModuleHandle("kernel32.dll"); + myCreateToolhelp32Snapshot = (CREATESNAPSHOT) + GetProcAddress(h, "CreateToolhelp32Snapshot"); + myProcess32First = (PROCESSWALK) + GetProcAddress(h, "Process32First"); + myProcess32Next = (PROCESSWALK) + GetProcAddress(h, "Process32Next"); + if (!myCreateToolhelp32Snapshot || !myProcess32First || !myProcess32Next) + return 0; + + myEnumProcesses = EnumProcessesW95; } - set_errno (ESRCH); - return (pid_t) -1; + return myEnumProcesses (lpidProcess, cb, cbneeded); } diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h new file mode 100644 index 000000000..4d9d71afd --- /dev/null +++ b/winsup/cygwin/pinfo.h @@ -0,0 +1,168 @@ +/******** Process Table ********/ + +/* Signal constants (have to define them here, unfortunately) */ + +enum +{ + __SIGFLUSH = -2, + __SIGSTRACE = -1, + __SIGCHILDSTOPPED = 0, + __SIGOFFSET = 3 +}; + +#define PSIZE 1024 +class _pinfo +{ +public: + /* Cygwin pid */ + pid_t pid; + + /* Various flags indicating the state of the process. See PID_ + constants below. */ + DWORD process_state; + + /* If hProcess is set, it's because it came from a + CreateProcess call. This means it's process relative + to the thing which created the process. That's ok because + we only use this handle from the parent. */ + HANDLE hProcess; + +#define PINFO_REDIR_SIZE ((DWORD) &(((_pinfo *)NULL)->hProcess) + sizeof (DWORD)) + + /* Parent process id. */ + pid_t ppid; + + /* dwProcessId contains the processid used for sending signals. It + * will be reset in a child process when it is capable of receiving + * signals. + */ + DWORD dwProcessId; + + /* Used to spawn a child for fork(), among other things. */ + char progname[MAX_PATH]; + + HANDLE parent_alive; + + /* User information. + The information is derived from the GetUserName system call, + with the name looked up in /etc/passwd and assigned a default value + if not found. This data resides in the shared data area (allowing + tasks to store whatever they want here) so it's for informational + purposes only. */ + uid_t uid; /* User ID */ + gid_t gid; /* Group ID */ + pid_t pgid; /* Process group ID */ + pid_t sid; /* Session ID */ + int ctty; /* Control tty */ + mode_t umask; + char username[MAX_USER_NAME]; /* user's name */ + + /* Extendend user information. + The information is derived from the internal_getlogin call + when on a NT system. */ + PSID psid; /* user's SID */ + char sidbuf[MAX_SID_LEN]; /* buffer for user's SID */ + char logsrv[MAX_HOST_NAME]; /* Logon server, may be FQDN */ + char domain[MAX_COMPUTERNAME_LENGTH+1]; /* Logon domain of the user */ + + /* token is needed if sexec should be called. It can be set by a call + to `set_impersonation_token()'. */ + HANDLE token; + BOOL impersonated; + uid_t orig_uid; /* Remains intact also after impersonation */ + uid_t orig_gid; /* Ditto */ + uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */ + gid_t real_gid; /* Ditto */ + + /* Filled when chroot() is called by the process or one of it's parents. + Saved without trailing backslash. */ + char root[MAX_PATH+1]; + size_t rootlen; + + /* Non-zero if process was stopped by a signal. */ + char stopsig; + + struct sigaction& getsig (int); + void copysigs (_pinfo* ); + sigset_t& getsigmask (); + void setsigmask (sigset_t); + LONG* getsigtodo (int); + HANDLE getthread2signal (); + void setthread2signal (void *); + + /* Resources used by process. */ + long start_time; + struct rusage rusage_self; + struct rusage rusage_children; + +private: + struct sigaction sigs[NSIG]; + sigset_t sig_mask; /* one set for everything to ignore. */ + LONG _sigtodo[NSIG + __SIGOFFSET]; + ThreadItem* thread2signal; // NULL means means thread any other means a pthread + +public: + /* Pointer to mmap'ed areas for this process. Set up by fork. */ + void *mmap_ptr; + + void record_death (); +}; + +class pinfo +{ + HANDLE h; + _pinfo *child; + int destroy; +public: + void init (pid_t n, DWORD create = 0); + pinfo () {} + pinfo (_pinfo *x): child (x) {} + pinfo (pid_t n) {init (n);} + pinfo (pid_t n, int create) {init (n, create);} + void release () + { + if (h) + { + UnmapViewOfFile (child); + CloseHandle (h); + h = NULL; + } + } + ~pinfo () + { + if (destroy && child) + release (); + } + + _pinfo *operator -> () const {return child;} + int operator == (pinfo *x) const {return x->child == child;} + int operator == (pinfo &x) const {return x.child == child;} + int operator == (void *x) const {return child == x;} + int operator == (int x) const {return (int) child == (int) x;} + int operator == (char *x) const {return (char *) child == x;} + _pinfo *operator * () const {return child;} + operator _pinfo * () const {return child;} + void remember () {destroy = 0; proc_subproc (PROC_ADDCHILD, (DWORD) this);} +}; + +#define ISSTATE(p, f) (!!((p)->process_state & f)) +#define NOTSTATE(p, f) (!((p)->process_state & f)) + +class winpids +{ + DWORD pidlist[16384]; +public: + DWORD npids; + void reset () { npids = 0; } + winpids (int) { reset (); } + winpids () { init (); }; + void init (); + int operator [] (int i) const {return pidlist[i];} +}; + +extern __inline pid_t +cygwin_pid (pid_t pid) +{ + return (pid_t) (os_being_run == winNT) ? pid : -(int) pid; +} +void __stdcall pinfo_init (PBYTE); diff --git a/winsup/cygwin/scandir.cc b/winsup/cygwin/scandir.cc index bbe582f12..6f9e30f95 100644 --- a/winsup/cygwin/scandir.cc +++ b/winsup/cygwin/scandir.cc @@ -12,7 +12,6 @@ #include <dirent.h> #include <stdlib.h> -#include <string.h> #include <errno.h> #include "winsup.h" diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index bc2dce518..fa2933125 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -25,12 +25,12 @@ details. */ #include <stdlib.h> #include <sys/time.h> -#include "winsup.h" -#include <wingdi.h> -#include <winuser.h> #include <netdb.h> #include <unistd.h> #include <stdio.h> +#include "winsup.h" +#include <wingdi.h> +#include <winuser.h> #include <winsock.h> #include "select.h" diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index f777a450e..aa3868c79 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -119,9 +119,6 @@ shared_info::initialize () /* Initialize the mount table. */ mount.init (); - /* Initialize the process table. */ - p.init (); - /* Initialize the queue of deleted files. */ delqueue.init (); diff --git a/winsup/cygwin/shared.h b/winsup/cygwin/shared.h index fa14492cb..851bad41b 100644 --- a/winsup/cygwin/shared.h +++ b/winsup/cygwin/shared.h @@ -41,140 +41,6 @@ public: void process_queue (); }; -/******** Process Table ********/ - -/* Signal constants (have to define them here, unfortunately) */ - -enum -{ - __SIGFLUSH = -2, - __SIGSTRACE = -1, - __SIGCHILDSTOPPED = 0, - __SIGOFFSET = 3 -}; - -class pinfo -{ - public: - - /* If hProcess is set, it's because it came from a - CreateProcess call. This means it's process relative - to the thing which created the process. That's ok because - we only use this handle from the parent. */ - HANDLE hProcess; - - HANDLE parent_alive; - - /* dwProcessId contains the processid used for sending signals. It - * will be reset in a child process when it is capable of receiving - * signals. - */ - DWORD dwProcessId; - - /* User information. - The information is derived from the GetUserName system call, - with the name looked up in /etc/passwd and assigned a default value - if not found. This data resides in the shared data area (allowing - tasks to store whatever they want here) so it's for informational - purposes only. */ - uid_t uid; /* User ID */ - gid_t gid; /* Group ID */ - pid_t pgid; /* Process group ID */ - pid_t sid; /* Session ID */ - int ctty; /* Control tty */ - mode_t umask; - char username[MAX_USER_NAME]; /* user's name */ - - /* Extendend user information. - The information is derived from the internal_getlogin call - when on a NT system. */ - PSID psid; /* user's SID */ - char sidbuf[MAX_SID_LEN]; /* buffer for user's SID */ - char logsrv[MAX_HOST_NAME]; /* Logon server, may be FQDN */ - char domain[MAX_COMPUTERNAME_LENGTH+1]; /* Logon domain of the user */ - - /* token is needed if sexec should be called. It can be set by a call - to `set_impersonation_token()'. */ - HANDLE token; - BOOL impersonated; - uid_t orig_uid; /* Remains intact also after impersonation */ - uid_t orig_gid; /* Ditto */ - uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */ - gid_t real_gid; /* Ditto */ - - /* Filled when chroot() is called by the process or one of it's parents. - Saved without trailing backslash. */ - char root[MAX_PATH+1]; - size_t rootlen; - - /* Non-zero if process was stopped by a signal. */ - char stopsig; - - struct sigaction& getsig (int); - void copysigs (pinfo *); - sigset_t& getsigmask (); - void setsigmask (sigset_t); - LONG* getsigtodo (int); - HANDLE getthread2signal (); - void setthread2signal (void *); - - /* Resources used by process. */ - long start_time; - struct rusage rusage_self; - struct rusage rusage_children; - -private: - struct sigaction sigs[NSIG]; - sigset_t sig_mask; /* one set for everything to ignore. */ - LONG _sigtodo[NSIG + __SIGOFFSET]; -#ifdef _MT_SAFE - ThreadItem* thread2signal; // NULL means means thread any other means a pthread -#endif - -public: - - /* Pointer to mmap'ed areas for this process. Set up by fork. */ - void *mmap_ptr; - - /* Used to spawn a child for fork(), among other things. */ - char progname[MAX_PATH]; - - #define PINFO_ZERO ((((pinfo *) NULL)->progname + 1) - ((char *) NULL)) - - /* Anything below this point is not zeroed automatically by allocate_pid */ - - /* The pid stays the same, while the hProcess moves due to execs. */ - pid_t pid; - /* Parent process id. */ - pid_t ppid; - - /* Various flags indicating the state of the process. See PID_ - constants below. */ - DWORD process_state; - - void record_death (int lock = 1); -}; - -#define ISSTATE(p, f) (!!((p)->process_state & f)) -#define NOTSTATE(p, f) (!((p)->process_state & f)) - -#define PSIZE 128 - -class pinfo_list -{ - public: - int next_pid; - pinfo vec[PSIZE]; - char lock_info[MAX_PATH + 1]; - pinfo * operator[] (pid_t x); - int size (void) { return PSIZE; } - pinfo *allocate_pid (void); - void init (void); -}; - -void __stdcall pinfo_init (PBYTE); -pinfo *__stdcall procinfo (int n); - enum { PROC_MAGIC = 0xaf08f000, @@ -221,7 +87,7 @@ void __stdcall init_child_info (DWORD, child_info *, int, HANDLE); extern child_info_fork *child_proc_info; /* Process info for this process */ -extern pinfo *myself; +extern pinfo myself; /* non-NULL if this process is a child of a cygwin process */ extern HANDLE parent_alive; @@ -499,8 +365,6 @@ class shared_info DWORD inited; public: - pinfo_list p; - /* FIXME: Doesn't work if more than one user on system. */ mount_info mount; diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 8ca6b7b8f..02870a637 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -108,7 +108,7 @@ static int kill_worker (pid_t pid, int sig) { int res = 0; - pinfo *dest = procinfo (pid); + pinfo dest (pid); BOOL sendSIGCONT; if (!dest) @@ -171,9 +171,10 @@ kill_pgrp (pid_t pid, int sig) sigproc_printf ("pid %d, sig %d", pid, sig); - for (int i = 0; i < cygwin_shared->p.size (); i++) + winpids pids; + for (unsigned i = 0; i < pids.npids; i++) { - pinfo *p = &cygwin_shared->p.vec[i]; + pinfo p = pids[i]; if (!proc_exists (p)) continue; diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index d1ddd91be..45cc37478 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -90,8 +90,8 @@ Static HANDLE wait_sig_inited = NULL; // Control synchronization of */ Static HANDLE events[PSIZE + 1] = {0}; // All my children's handles++ #define hchildren (events + 1) // Where the children handles begin -Static pinfo *pchildren[PSIZE] = {NULL};// All my children info -Static pinfo *zombies[PSIZE] = {NULL}; // All my deceased children info +Static pinfo pchildren[PSIZE] = {pinfo ()};// All my children info +Static pinfo zombies[PSIZE] = {pinfo ()}; // All my deceased children info Static int nchildren = 0; // Number of active children Static int nzombies = 0; // Number of deceased children @@ -108,11 +108,11 @@ int NO_COPY pending_signals = 0; // TRUE if signals pending */ static int __stdcall checkstate (waitq *); static __inline__ BOOL get_proc_lock (DWORD, DWORD); -static HANDLE __stdcall getsem (pinfo *, const char *, int, int); +static HANDLE __stdcall getsem (_pinfo *, const char *, int, int); static void __stdcall remove_child (int); static void __stdcall remove_zombie (int); static DWORD WINAPI wait_sig (VOID *arg); -static int __stdcall stopped_or_terminated (waitq *, pinfo *); +static int __stdcall stopped_or_terminated (waitq *, _pinfo *); static DWORD WINAPI wait_subproc (VOID *); /* Determine if the parent process is alive. @@ -168,7 +168,7 @@ wait_for_me () } static BOOL __stdcall -proc_can_be_signalled (pinfo *p) +proc_can_be_signalled (_pinfo *p) { if (p == myself_nowait || p == myself_nowait_nonmain || p == myself) { @@ -181,11 +181,18 @@ proc_can_be_signalled (pinfo *p) (PID_ACTIVE | PID_IN_USE)); } +BOOL __stdcall +proc_exists (pid_t pid) +{ + pinfo p (pid); + return proc_exists (p); +} + /* Test to determine if a process really exists and is processing * signals. */ BOOL __stdcall -proc_exists (pinfo *p) +proc_exists (_pinfo *p) { HANDLE h; @@ -225,7 +232,7 @@ proc_exists (pinfo *p) /* If the parent pid does not exist, clean this process out of the pinfo * table. It must have died abnormally. */ - if ((p->pid == p->ppid) || (p->ppid == 1) || !proc_exists (procinfo (p->ppid))) + if ((p->pid == p->ppid) || (p->ppid == 1) || !proc_exists (p->ppid)) { p->hProcess = NULL; p->process_state = PID_NOT_IN_USE; @@ -235,14 +242,14 @@ proc_exists (pinfo *p) /* Handle all subprocess requests */ -#define vchild ((pinfo *) val) +#define vchild (*((pinfo *) val)) int __stdcall proc_subproc (DWORD what, DWORD val) { int rc = 1; int potential_match; DWORD exitcode; - pinfo *child; + _pinfo *child; int clearing; waitq *w; @@ -292,23 +299,22 @@ proc_subproc (DWORD what, DWORD val) */ case PROC_CHILDTERMINATED: rc = 0; - child = pchildren[val]; if (GetExitCodeProcess (hchildren[val], &exitcode) && - hchildren[val] != child->hProcess) + hchildren[val] != pchildren[val]->hProcess) { sip_printf ("pid %d[%d], reparented old hProcess %p, new %p", - child->pid, val, hchildren[val], child->hProcess); + pchildren[val]->pid, val, hchildren[val], pchildren[val]->hProcess); ForceCloseHandle1 (hchildren[val], childhProc); - hchildren[val] = child->hProcess; /* Filled out by child */ - ProtectHandle1 (child->hProcess, childhProc); + hchildren[val] = pchildren[val]->hProcess; /* Filled out by child */ + ProtectHandle1 (pchildren[val]->hProcess, childhProc); break; // This was an exec() } sip_printf ("pid %d[%d] terminated, handle %p, nchildren %d, nzombies %d", - child->pid, val, hchildren[val], nchildren, nzombies); - remove_child (val); // Remove from children arrays - zombies[nzombies++] = child; // Add to zombie array - child->process_state = PID_ZOMBIE;// Walking dead + pchildren[val]->pid, val, hchildren[val], nchildren, nzombies); + zombies[nzombies] = pchildren[val]; // Add to zombie array + zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead + remove_child (val); // Remove from children array if (!proc_loop_wait) // Don't bother if wait_subproc is break; // exiting @@ -381,7 +387,7 @@ proc_subproc (DWORD what, DWORD val) if (wval->pid <= 0) child = NULL; // Not looking for a specific pid - else if ((child = procinfo (wval->pid)) == NULL) + else if (!proc_exists (wval->pid)) /* CGF FIXME -- test that this is one of mine */ goto out; // invalid pid. flag no such child wval->status = 0; // Don't know status yet @@ -480,50 +486,49 @@ proc_terminate (void) sync_proc_subproc->acquire(WPSP); (void) proc_subproc (PROC_CLEARWAIT, 1); - lock_pinfo_for_update (INFINITE); /* Clean out zombie processes from the pid list. */ int i; for (i = 0; i < nzombies; i++) { - pinfo *child; - if ((child = zombies[i])->hProcess) + if (zombies[i]->hProcess) { - ForceCloseHandle1 (child->hProcess, childhProc); - child->hProcess = NULL; + ForceCloseHandle1 (zombies[i]->hProcess, childhProc); + zombies[i]->hProcess = NULL; } - child->process_state = PID_NOT_IN_USE; + zombies[i]->process_state = PID_NOT_IN_USE; /* CGF FIXME - still needed? */ + zombies[i].release(); } /* Disassociate my subprocesses */ for (i = 0; i < nchildren; i++) { - pinfo *child; - if ((child = pchildren[i])->process_state == PID_NOT_IN_USE) + pinfo child; /* CGF FIXME */ + if (pchildren[i]->process_state == PID_NOT_IN_USE) continue; // Should never happen - if (!child->hProcess) - sip_printf ("%d(%d) hProcess cleared already?", child->pid, - child->dwProcessId); + if (!pchildren[i]->hProcess) + sip_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid, + pchildren[i]->dwProcessId); else { - ForceCloseHandle1 (child->hProcess, childhProc); - child->hProcess = NULL; - if (!proc_exists (child)) + ForceCloseHandle1 (pchildren[i]->hProcess, childhProc); + pchildren[i]->hProcess = NULL; + if (!proc_exists (pchildren[i])) { - sip_printf ("%d(%d) doesn't exist", child->pid, - child->dwProcessId); - child->process_state = PID_NOT_IN_USE; /* a reaped child */ + sip_printf ("%d(%d) doesn't exist", pchildren[i]->pid, + pchildren[i]->dwProcessId); + pchildren[i]->process_state = PID_NOT_IN_USE; /* a reaped child CGF FIXME -- still needed? */ } else { - sip_printf ("%d(%d) closing active child handle", child->pid, - child->dwProcessId); - child->ppid = 1; - if (child->pgid == myself->pid) - child->process_state |= PID_ORPHANED; + sip_printf ("%d(%d) closing active child handle", pchildren[i]->pid, + pchildren[i]->dwProcessId); + pchildren[i]->ppid = 1; + if (pchildren[i]->pgid == myself->pid) + pchildren[i]->process_state |= PID_ORPHANED; } } + pchildren[i].release (); } - unlock_pinfo (); nchildren = nzombies = 0; /* Attempt to close and release sync_proc_subproc in a @@ -706,7 +711,7 @@ sigproc_terminate (void) * completed before returning. */ int __stdcall -sig_send (pinfo *p, int sig, DWORD ebp) +sig_send (_pinfo *p, int sig, DWORD ebp) { int rc = 1; DWORD tid = GetCurrentThreadId (); @@ -717,7 +722,7 @@ sig_send (pinfo *p, int sig, DWORD ebp) sigframe thisframe; if (p == myself_nowait_nonmain) - p = (tid == mainthread.id) ? myself : myself_nowait; + p = (tid == mainthread.id) ? (_pinfo *) myself : myself_nowait; if (!(its_me = (p == NULL || p == myself || p == myself_nowait))) wait_for_completion = FALSE; else @@ -888,7 +893,7 @@ subproc_init (void) by fork/spawn/exec. */ void __stdcall -init_child_info (DWORD chtype, child_info *ch, int pid, HANDLE subproc_ready) +init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready) { subproc_init (); memset (ch, 0, sizeof *ch); @@ -912,7 +917,7 @@ static int __stdcall checkstate (waitq *w) { int i, x, potential_match = 0; - pinfo *child; + _pinfo *child; sip_printf ("nchildren %d, nzombies %d", nchildren, nzombies); @@ -949,7 +954,7 @@ out: /* Get or create a process specific semaphore used in message passing. */ static HANDLE __stdcall -getsem (pinfo *p, const char *str, int init, int max) +getsem (_pinfo *p, const char *str, int init, int max) { HANDLE h; @@ -1047,6 +1052,10 @@ remove_zombie (int ci) { sip_printf ("removing %d, pid %d, nzombies %d", ci, zombies[ci]->pid, nzombies); + + if (zombies[ci]) + zombies[ci].release (); + if (ci < --nzombies) zombies[ci] = zombies[nzombies]; @@ -1064,7 +1073,7 @@ remove_zombie (int ci) * 0 if child does not match parent_w->next criteria */ static int __stdcall -stopped_or_terminated (waitq *parent_w, pinfo *child) +stopped_or_terminated (waitq *parent_w, _pinfo *child) { int potential_match; waitq *w = parent_w->next; @@ -1096,7 +1105,7 @@ stopped_or_terminated (waitq *parent_w, pinfo *child) w->status = (child->stopsig << 8) | 0x7f; child->stopsig = 0; } - else + else /* Should only get here when child has been moved to the zombies array */ { DWORD status; if (!GetExitCodeProcess (child->hProcess, &status)) diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 581a5b5bd..f7b36a843 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -92,13 +92,17 @@ void __stdcall sig_clear (int); void __stdcall sig_set_pending (int); int __stdcall handle_sigsuspend (sigset_t); +int __stdcall proc_subproc (DWORD, DWORD); + +#include "pinfo.h" + void __stdcall proc_terminate (); void __stdcall sigproc_init (); void __stdcall subproc_init (); void __stdcall sigproc_terminate (); -BOOL __stdcall proc_exists (pinfo *); -int __stdcall proc_subproc (DWORD, DWORD); -int __stdcall sig_send (pinfo *, int, DWORD ebp = 0); +BOOL __stdcall proc_exists (_pinfo *); +BOOL __stdcall proc_exists (pid_t); +int __stdcall sig_send (_pinfo *, int, DWORD ebp = 0); void __stdcall signal_fixup_after_fork (); extern char myself_nowait_dummy[]; @@ -110,7 +114,5 @@ extern HANDLE hExeced; // Process handle of new window #define allow_sig_dispatch(n) __allow_sig_dispatch (__FILE__, __LINE__, (n)) -#define myself_nowait ((pinfo *)myself_nowait_dummy) -#define myself_nowait_nonmain ((pinfo *)myself_nowait_nonmain_dummy) -#define proc_register(child) \ - proc_subproc (PROC_ADDCHILD, (DWORD) (child)) +#define myself_nowait ((_pinfo *)myself_nowait_dummy) +#define myself_nowait_nonmain ((_pinfo *)myself_nowait_nonmain_dummy) 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; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 6123a47a0..154c05a1f 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -21,9 +21,9 @@ details. */ #include <errno.h> #include <limits.h> #include "winsup.h" +#include <unistd.h> #include <winnls.h> #include <lmcons.h> /* for UNLEN */ -#include <unistd.h> extern BOOL allow_ntsec; @@ -1413,8 +1413,7 @@ pathconf (const char *file, int v) } } -extern "C" -char * +extern "C" char * ctermid (char *str) { static NO_COPY char buf[16]; @@ -1714,23 +1713,25 @@ setpgid (pid_t pid, pid_t pgid) set_errno (EINVAL); goto out; } - pinfo *p; - p = procinfo (pid); - if (p == NULL) - { - set_errno (ESRCH); - goto out; - } - /* A process may only change the process group of itself and its children */ - if (p == myself || p->ppid == myself->pid) - { - p->pgid = pgid; - res = 0; - } else { - set_errno (EPERM); - goto out; + pinfo p (pid); + if (!p) + { + set_errno (ESRCH); + goto out; + } + /* A process may only change the process group of itself and its children */ + if (p == myself || p->ppid == myself->pid) + { + p->pgid = pgid; + res = 0; + } + else + { + set_errno (EPERM); + goto out; + } } out: syscall_printf ("pid %d, pgid %d, res %d", pid, pgid, res); @@ -1744,7 +1745,7 @@ getpgid (pid_t pid) if (pid == 0) pid = getpid (); - pinfo *p = procinfo (pid); + pinfo p (pid); if (p == 0) { set_errno (ESRCH); @@ -1824,7 +1825,7 @@ setuid (uid_t uid) return ret; } -extern char *internal_getlogin (struct pinfo *pi); +extern char *internal_getlogin (_pinfo *pi); /* seteuid: standards? */ extern "C" @@ -1863,7 +1864,7 @@ seteuid (uid_t uid) myself->impersonated = TRUE; } - struct pinfo pi; + struct _pinfo pi; pi.psid = (PSID) pi.sidbuf; /* pi.token is used in internal_getlogin() to determine if impersonation is active. If so, the token is used for diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 5ee9162f7..3aa25ba5c 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -10,17 +10,17 @@ details. */ #include <pwd.h> #include "winsup.h" +#include <unistd.h> #include <winnls.h> #include <utmp.h> #include <limits.h> -#include <unistd.h> #include "autoload.h" #include <stdlib.h> #include <wchar.h> #include <lm.h> char * -internal_getlogin (struct pinfo *pi) +internal_getlogin (_pinfo *pi) { if (! pi) api_fatal ("pinfo pointer is NULL!\n"); diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc index 30b8ef885..63ad06783 100644 --- a/winsup/cygwin/wait.cc +++ b/winsup/cygwin/wait.cc @@ -47,6 +47,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r) waitq *w; HANDLE waitfor; +sigproc_printf ("here"); if (options & ~(WNOHANG | WUNTRACED)) { set_errno (EINVAL); diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 114678548..330c38ce2 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -178,11 +178,8 @@ class host_dependent_constants extern host_dependent_constants host_dependent; /* Events/mutexes */ -extern HANDLE pinfo_mutex; extern HANDLE title_mutex; - - /*************************** Per Thread ******************************/ #define PER_THREAD_FORK_CLEAR ((void *)0xffffffff) @@ -283,7 +280,7 @@ extern unsigned int signal_shift_subtract; #endif #define api_fatal(fmt, args...) \ - __api_fatal ("%P: *** " fmt, ## args) + __api_fatal ("%P: *** " fmt,##args) #undef issep #define issep(ch) (strchr (" \t\n\r", (ch)) != NULL) @@ -378,13 +375,12 @@ void __stdcall mark (const char *, int); extern "C" int _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv, const char *const *envp); -int __stdcall spawn_guts (HANDLE hToken, const char *prog_arg, - const char *const *argv, const char *const envp[], - pinfo *child, int mode); + +extern void __stdcall exec_fixup_after_fork (); /* For mmaps across fork(). */ int __stdcall recreate_mmaps_after_fork (void *); -void __stdcall set_child_mmap_ptr (pinfo *); +void __stdcall set_child_mmap_ptr (_pinfo *); /* String manipulation */ char *__stdcall strccpy (char *s1, const char **s2, char c); @@ -401,7 +397,7 @@ long __stdcall to_time_t (FILETIME * ptr); int __stdcall lock_pinfo_for_update (DWORD timeout); #endif void unlock_pinfo (void); -pinfo *__stdcall set_myself (pinfo *); +void _stdcall set_myself (pid_t pid); /* Retrieve a security descriptor that allows all access */ SECURITY_DESCRIPTOR *__stdcall get_null_sd (void); @@ -500,7 +496,7 @@ win_env * __stdcall getwinenv (const char *name, const char *posix = NULL); void __stdcall update_envptrs (); char * __stdcall winenv (const char * const *, int); extern char **__cygwin_environ, ***main_environ; -extern char __stdcall **cur_environ (); +extern "C" char __stdcall **cur_environ (); #define environ (cur_environ ()) /* The title on program start. */ |