Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2000-07-29 20:24:59 +0400
committerChristopher Faylor <me@cgf.cx>2000-07-29 20:24:59 +0400
commit84c7d4093270dc07de4531ab6648a12daaff77c3 (patch)
tree067ed4cf0bffd057a63b2f472bcab39854f86c17 /winsup/cygwin/pinfo.cc
parent53211514a0466b7e29f6f53c11b769befddfdfa6 (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/pinfo.cc')
-rw-r--r--winsup/cygwin/pinfo.cc380
1 files changed, 164 insertions, 216 deletions
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);
}