* exceptions.cc (set_console_handler): Don't allocate
console_handler_thread_waiter. It is obsolete. (ctrl_c_handler): Don't use console_handler_thread_waiter. * path.cc (hash_path_name): Fix handling of relative names. Make case insensitive. * path.h (suffix_info): Use initializers. * pinfo.h (_pinfo): Avoid initializers for null case. * resource.cc (fill_rusage): Zero rest of rusage structure. * security.cc (set_process_privileges): Don't reopen parent process. Just use hMainProc. * signal.cc (signal): Track when a signal handler has been used. (sigaction): Ditto. * sigproc.cc (pchildren): Use default initializer. (zombies): Ditto. (sigproc_terminate): Avoid closing handles that will be closed on exit anyway. (wait_sig): Send signal to "parent" on EXECing, not FORKing. (wait_subproc): Send SIGCHLD here rather than in proc_wait to avoid potential muto conflicts. * sigproc.h (sigthread): Don't initialize to zero. It's the default. * spawn.cc (spawn_guts): Fill in resources from exec parent prior to termination. * sync.h (muto): Don't initialize to zero. * syscalls.cc (close_all_files): Use one lock around entire loop and call fhandler close/release stuff directly. (_read): Don't use ready_for_read if there are not signal handlers active. * dcrt0.cc (dll_crt0_1): Fix display of "title". (do_exit): Use pinfo exit method to exit. (__api_fatal): Ditto. * exceptions.cc (signal_exit): Ditto. * fork.cc (fork_child): Remove debugging stuff. Use pinfo_fixup_after fork in place of exec_fixup_after_fork. * pinfo.cc (pinfo_fixup_after_fork): New method. (pinfo_fixup_in_spawned_child): Ditto. (_pinfo::exit): New method. (_pinfo::init): Remove recursion. Detect pathological case where pinfo structure already exists for new pid. * pinfo.h (_pinfo): Reorganize slightly. Add new method and new function declarations. * sigproc.cc (proc_exists): Previous simplification was a little to simple. Try harder to detect if a process exists. (proc_terminate): Use PID_EXITED setting to determine if process is still around. (WFSO): Remove debugging statement. (WFMO): Ditto. * spawn.cc (exec_fixup_after_fork): Eliminate. (spawn_guts): Always set old_title to NULL. Is it really needed? Move hexec_proc to pinfo.cc. Call pinfo_fixup_in_spawned_child to eliminate handle link after a spawn. * include/sys/cygwin.h: Remove PID_NOT_IN_USE. Add PID_EXITED.
This commit is contained in:
parent
fdc614360f
commit
1dc16fc74b
|
@ -1,3 +1,60 @@
|
||||||
|
Sat Oct 14 21:24:16 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* exceptions.cc (set_console_handler): Don't allocate
|
||||||
|
console_handler_thread_waiter. It is obsolete.
|
||||||
|
(ctrl_c_handler): Don't use console_handler_thread_waiter.
|
||||||
|
* path.cc (hash_path_name): Fix handling of relative names. Make case
|
||||||
|
insensitive.
|
||||||
|
* path.h (suffix_info): Use initializers.
|
||||||
|
* pinfo.h (_pinfo): Avoid initializers for null case.
|
||||||
|
* resource.cc (fill_rusage): Zero rest of rusage structure.
|
||||||
|
* security.cc (set_process_privileges): Don't reopen parent process.
|
||||||
|
Just use hMainProc.
|
||||||
|
* signal.cc (signal): Track when a signal handler has been used.
|
||||||
|
(sigaction): Ditto.
|
||||||
|
* sigproc.cc (pchildren): Use default initializer.
|
||||||
|
(zombies): Ditto.
|
||||||
|
(sigproc_terminate): Avoid closing handles that will be closed on exit
|
||||||
|
anyway.
|
||||||
|
(wait_sig): Send signal to "parent" on EXECing, not FORKing.
|
||||||
|
(wait_subproc): Send SIGCHLD here rather than in proc_wait to avoid
|
||||||
|
potential muto conflicts.
|
||||||
|
* sigproc.h (sigthread): Don't initialize to zero. It's the default.
|
||||||
|
* spawn.cc (spawn_guts): Fill in resources from exec parent prior to
|
||||||
|
termination.
|
||||||
|
* sync.h (muto): Don't initialize to zero.
|
||||||
|
* syscalls.cc (close_all_files): Use one lock around entire loop and
|
||||||
|
call fhandler close/release stuff directly.
|
||||||
|
(_read): Don't use ready_for_read if there are not signal handlers
|
||||||
|
active.
|
||||||
|
|
||||||
|
Sat Oct 14 12:24:24 2000 Christopher Faylor <cgf@cygnus.com>
|
||||||
|
|
||||||
|
* dcrt0.cc (dll_crt0_1): Fix display of "title".
|
||||||
|
(do_exit): Use pinfo exit method to exit.
|
||||||
|
(__api_fatal): Ditto.
|
||||||
|
* exceptions.cc (signal_exit): Ditto.
|
||||||
|
* fork.cc (fork_child): Remove debugging stuff. Use pinfo_fixup_after
|
||||||
|
fork in place of exec_fixup_after_fork.
|
||||||
|
* pinfo.cc (pinfo_fixup_after_fork): New method.
|
||||||
|
(pinfo_fixup_in_spawned_child): Ditto.
|
||||||
|
(_pinfo::exit): New method.
|
||||||
|
(_pinfo::init): Remove recursion. Detect pathological case where pinfo
|
||||||
|
structure already exists for new pid.
|
||||||
|
* pinfo.h (_pinfo): Reorganize slightly. Add new method and new
|
||||||
|
function declarations.
|
||||||
|
* sigproc.cc (proc_exists): Previous simplification was a little to
|
||||||
|
simple. Try harder to detect if a process exists.
|
||||||
|
(proc_terminate): Use PID_EXITED setting to determine if process is
|
||||||
|
still around.
|
||||||
|
(WFSO): Remove debugging statement.
|
||||||
|
(WFMO): Ditto.
|
||||||
|
* spawn.cc (exec_fixup_after_fork): Eliminate.
|
||||||
|
(spawn_guts): Always set old_title to NULL. Is it really needed? Move
|
||||||
|
hexec_proc to pinfo.cc. Call pinfo_fixup_in_spawned_child to eliminate
|
||||||
|
handle link after a spawn.
|
||||||
|
* include/sys/cygwin.h: Remove PID_NOT_IN_USE. Add PID_EXITED.
|
||||||
|
|
||||||
Sat Oct 14 10:54:00 2000 Corinna Vinschen <corinna@vinschen.de>
|
Sat Oct 14 10:54:00 2000 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* cygwin.din: Add symbol hstrerror.
|
* cygwin.din: Add symbol hstrerror.
|
||||||
|
|
|
@ -683,8 +683,8 @@ dll_crt0_1 ()
|
||||||
cygheap_fixup_in_child (spawn_info->parent, 1);
|
cygheap_fixup_in_child (spawn_info->parent, 1);
|
||||||
if (!spawn_info->moreinfo->myself_pinfo ||
|
if (!spawn_info->moreinfo->myself_pinfo ||
|
||||||
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
|
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
|
||||||
hMainProc, &h, 0, 0,
|
hMainProc, &h, 0, 0,
|
||||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
|
||||||
h = NULL;
|
h = NULL;
|
||||||
set_myself (mypid, h);
|
set_myself (mypid, h);
|
||||||
__argc = spawn_info->moreinfo->argc;
|
__argc = spawn_info->moreinfo->argc;
|
||||||
|
@ -769,18 +769,6 @@ dll_crt0_1 ()
|
||||||
|
|
||||||
line = strcpy ((char *) alloca (strlen (line) + 1), line);
|
line = strcpy ((char *) alloca (strlen (line) + 1), line);
|
||||||
|
|
||||||
/* Set new console title if appropriate. */
|
|
||||||
|
|
||||||
if (display_title && !dynamically_loaded)
|
|
||||||
{
|
|
||||||
char *cp = line;
|
|
||||||
if (strip_title_path)
|
|
||||||
for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
|
|
||||||
if (isdirsep (*ptr))
|
|
||||||
cp = ptr + 1;
|
|
||||||
set_console_title (cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate fdtab */
|
/* Allocate fdtab */
|
||||||
dtable_init ();
|
dtable_init ();
|
||||||
|
|
||||||
|
@ -823,6 +811,18 @@ dll_crt0_1 ()
|
||||||
/* Set up __progname for getopt error call. */
|
/* Set up __progname for getopt error call. */
|
||||||
__progname = __argv[0];
|
__progname = __argv[0];
|
||||||
|
|
||||||
|
/* Set new console title if appropriate. */
|
||||||
|
|
||||||
|
if (display_title && !dynamically_loaded)
|
||||||
|
{
|
||||||
|
char *cp = __progname;
|
||||||
|
if (strip_title_path)
|
||||||
|
for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
|
||||||
|
if (isdirsep (*ptr))
|
||||||
|
cp = ptr + 1;
|
||||||
|
set_console_title (cp);
|
||||||
|
}
|
||||||
|
|
||||||
cygwin_finished_initializing = 1;
|
cygwin_finished_initializing = 1;
|
||||||
/* Call init of loaded dlls. */
|
/* Call init of loaded dlls. */
|
||||||
dlls.init ();
|
dlls.init ();
|
||||||
|
@ -1057,9 +1057,8 @@ do_exit (int status)
|
||||||
|
|
||||||
shared_terminate ();
|
shared_terminate ();
|
||||||
|
|
||||||
sigproc_printf ("calling ExitProcess %d", n);
|
|
||||||
minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
|
minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
|
||||||
ExitProcess (n);
|
myself->exit (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
|
@ -1099,7 +1098,7 @@ __api_fatal (const char *fmt, ...)
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
(void) try_to_debug ();
|
(void) try_to_debug ();
|
||||||
#endif
|
#endif
|
||||||
ExitProcess (1);
|
myself->exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -16,12 +16,22 @@ details. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#ifndef DEBUGGING0
|
||||||
DWORD __stdcall WFSO (HANDLE, DWORD);
|
DWORD __stdcall WFSO (HANDLE, DWORD);
|
||||||
DWORD __stdcall WFMO (DWORD, CONST HANDLE *, BOOL, DWORD);
|
DWORD __stdcall WFMO (DWORD, CONST HANDLE *, BOOL, DWORD);
|
||||||
|
#else
|
||||||
|
DWORD __stdcall WFSO (const char *fn, int ln, HANDLE, DWORD);
|
||||||
|
DWORD __stdcall WFMO (const char *fn, int ln, DWORD, CONST HANDLE *, BOOL, DWORD);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DEBUGGING0
|
||||||
#define WaitForSingleObject WFSO
|
#define WaitForSingleObject WFSO
|
||||||
#define WaitForMultipleObject WFMO
|
#define WaitForMultipleObject WFMO
|
||||||
|
#else
|
||||||
|
#define WaitForSingleObject(a, b) WFSO (__FUNCTION__, __LINE__, a, b)
|
||||||
|
#define WaitForMultipleObject(a, b, c, d) WFMO (__FUNCTION__, __LINE__, a, b, c, d)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(_DEBUG_H_)
|
#if !defined(_DEBUG_H_)
|
||||||
#define _DEBUG_H_
|
#define _DEBUG_H_
|
||||||
|
|
|
@ -47,7 +47,6 @@ static NO_COPY int exit_already = 0;
|
||||||
static NO_COPY muto *mask_sync = NULL;
|
static NO_COPY muto *mask_sync = NULL;
|
||||||
|
|
||||||
HMODULE NO_COPY cygwin_hmodule;
|
HMODULE NO_COPY cygwin_hmodule;
|
||||||
HANDLE NO_COPY console_handler_thread_waiter = NULL;
|
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
|
@ -126,10 +125,6 @@ set_console_handler ()
|
||||||
sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
|
sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
|
||||||
get_null_sd ();
|
get_null_sd ();
|
||||||
|
|
||||||
/* Allocate the event needed for ctrl_c_handler synchronization with
|
|
||||||
wait_sig. */
|
|
||||||
if (!console_handler_thread_waiter)
|
|
||||||
CreateEvent (&sec_none_nih, TRUE, TRUE, NULL);
|
|
||||||
(void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
|
(void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
|
||||||
if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
|
if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
|
||||||
system_printf ("SetConsoleCtrlHandler failed, %E");
|
system_printf ("SetConsoleCtrlHandler failed, %E");
|
||||||
|
@ -825,11 +820,6 @@ ctrl_c_handler (DWORD type)
|
||||||
if (type == CTRL_LOGOFF_EVENT)
|
if (type == CTRL_LOGOFF_EVENT)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Wait for sigproc_init to tell us that it's safe to send something.
|
|
||||||
This event will always be in a signalled state when wait_sig is
|
|
||||||
ready to process signals. */
|
|
||||||
(void) WaitForSingleObject (console_handler_thread_waiter, 5000);
|
|
||||||
|
|
||||||
if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
|
if ((type == CTRL_CLOSE_EVENT) || (type == CTRL_SHUTDOWN_EVENT))
|
||||||
/* Return FALSE to prevent an "End task" dialog box from appearing
|
/* Return FALSE to prevent an "End task" dialog box from appearing
|
||||||
for each Cygwin process window that's open when the computer
|
for each Cygwin process window that's open when the computer
|
||||||
|
@ -1005,7 +995,7 @@ signal_exit (int rc)
|
||||||
{
|
{
|
||||||
rc = EXIT_SIGNAL | (rc << 8);
|
rc = EXIT_SIGNAL | (rc << 8);
|
||||||
if (exit_already++)
|
if (exit_already++)
|
||||||
ExitProcess (rc);
|
myself->exit (rc);
|
||||||
|
|
||||||
/* We'd like to stop the main thread from executing but when we do that it
|
/* We'd like to stop the main thread from executing but when we do that it
|
||||||
causes random, inexplicable hangs. So, instead, we set up the priority
|
causes random, inexplicable hangs. So, instead, we set up the priority
|
||||||
|
|
|
@ -225,8 +225,6 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
||||||
{
|
{
|
||||||
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
|
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
|
||||||
myself->pid, myself->ppid, __builtin_frame_address (0));
|
myself->pid, myself->ppid, __builtin_frame_address (0));
|
||||||
child_info_fork ch;
|
|
||||||
stack_base (ch);
|
|
||||||
|
|
||||||
/* Restore the inheritance state as in parent
|
/* Restore the inheritance state as in parent
|
||||||
Don't call setuid here! The flags are already set. */
|
Don't call setuid here! The flags are already set. */
|
||||||
|
@ -240,9 +238,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_with_parent ("after longjmp.", TRUE);
|
sync_with_parent ("after longjmp.", TRUE);
|
||||||
debug_printf ("hParent %p", hParent);
|
|
||||||
ProtectHandle (hParent);
|
ProtectHandle (hParent);
|
||||||
// small_printf ("child 1 first_dll %p, load_dlls %d\n", first_dll, load_dlls);
|
sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d\n", hParent, first_dll, load_dlls);
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
char c;
|
char c;
|
||||||
|
@ -270,9 +267,9 @@ debug_printf ("hParent %p", hParent);
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
|
||||||
|
pinfo_fixup_after_fork ();
|
||||||
fdtab.fixup_after_fork (hParent);
|
fdtab.fixup_after_fork (hParent);
|
||||||
signal_fixup_after_fork ();
|
signal_fixup_after_fork ();
|
||||||
exec_fixup_after_fork ();
|
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ typedef enum
|
||||||
/* Flags associated with process_state */
|
/* Flags associated with process_state */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PID_NOT_IN_USE = 0x0000, // Free entry.
|
|
||||||
PID_IN_USE = 0x0001, // Entry in use.
|
PID_IN_USE = 0x0001, // Entry in use.
|
||||||
PID_ZOMBIE = 0x0002, // Child exited: no parent wait.
|
PID_ZOMBIE = 0x0002, // Child exited: no parent wait.
|
||||||
PID_STOPPED = 0x0004, // Waiting for SIGCONT.
|
PID_STOPPED = 0x0004, // Waiting for SIGCONT.
|
||||||
|
@ -86,7 +85,8 @@ enum
|
||||||
// all execed or forked processes.
|
// all execed or forked processes.
|
||||||
PID_UNUSED2 = 0x2000, // child has execed
|
PID_UNUSED2 = 0x2000, // child has execed
|
||||||
PID_EXECED = 0x4000, // redirect to original pid info block
|
PID_EXECED = 0x4000, // redirect to original pid info block
|
||||||
PID_NOREDIR = 0x8000 // don't redirect if execed
|
PID_NOREDIR = 0x8000, // don't redirect if execed
|
||||||
|
PID_EXITED = 0x80000000 // Free entry.
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WINVER
|
#ifdef WINVER
|
||||||
|
|
|
@ -2396,8 +2396,8 @@ hash_path_name (unsigned long hash, const char *name)
|
||||||
{
|
{
|
||||||
char *nn, *newname = (char *) alloca (strlen (name) + 2);
|
char *nn, *newname = (char *) alloca (strlen (name) + 2);
|
||||||
nn = strncpy (newname, name, 2);
|
nn = strncpy (newname, name, 2);
|
||||||
if (islower (*nn))
|
if (isupper (*nn))
|
||||||
*newname = toupper (*nn);
|
*newname = tolower (*nn);
|
||||||
*(nn += 2) = '\0';
|
*(nn += 2) = '\0';
|
||||||
name += 2;
|
name += 2;
|
||||||
if (*name != '\\')
|
if (*name != '\\')
|
||||||
|
@ -2415,12 +2415,12 @@ hash_path_name (unsigned long hash, const char *name)
|
||||||
Otherwise the inodes same will differ depending on whether a file is
|
Otherwise the inodes same will differ depending on whether a file is
|
||||||
referenced with an absolute value or relatively. */
|
referenced with an absolute value or relatively. */
|
||||||
|
|
||||||
if (*name != '\\')
|
if (!hash && !isabspath (name))
|
||||||
{
|
{
|
||||||
hash = cygcwd.get_hash ();
|
hash = cygcwd.get_hash ();
|
||||||
if (name[0] == '.' && name[1] == '\0')
|
if (name[0] == '.' && name[1] == '\0')
|
||||||
return hash;
|
return hash;
|
||||||
hash = hash_path_name (hash, "\\");
|
hash += hash_path_name (hash, "\\");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2429,7 +2429,8 @@ hashit:
|
||||||
\a\b\. but allow a single \ if that's all there is. */
|
\a\b\. but allow a single \ if that's all there is. */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hash += *name + (*name << 17);
|
int ch = tolower(*name);
|
||||||
|
hash += ch + (ch << 17);
|
||||||
hash ^= hash >> 2;
|
hash ^= hash >> 2;
|
||||||
}
|
}
|
||||||
while (*++name != '\0' &&
|
while (*++name != '\0' &&
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct suffix_info
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int addon;
|
int addon;
|
||||||
suffix_info (const char *s, int addit = 0) {name = s, addon = addit;}
|
suffix_info (const char *s, int addit = 0): name (s), addon (addit) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pathconv_arg
|
enum pathconv_arg
|
||||||
|
|
|
@ -24,11 +24,41 @@ details. */
|
||||||
#include "perprocess.h"
|
#include "perprocess.h"
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
static char NO_COPY pinfo_dummy[sizeof(pinfo)] = {0};
|
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 HANDLE hexec_proc = NULL;
|
||||||
|
|
||||||
|
void __stdcall
|
||||||
|
pinfo_fixup_after_fork ()
|
||||||
|
{
|
||||||
|
if (hexec_proc)
|
||||||
|
CloseHandle (hexec_proc);
|
||||||
|
|
||||||
|
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
|
||||||
|
TRUE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
system_printf ("couldn't save current process handle %p, %E", hMainProc);
|
||||||
|
hexec_proc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __stdcall
|
||||||
|
pinfo_fixup_in_spawned_child (HANDLE hchild)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
if (!hexec_proc)
|
||||||
|
return;
|
||||||
|
if (!DuplicateHandle (hchild, hexec_proc, hMainProc, &h, 0, TRUE,
|
||||||
|
DUPLICATE_CLOSE_SOURCE))
|
||||||
|
system_printf ("couldn't close handle %p in child, %E", hexec_proc);
|
||||||
|
else
|
||||||
|
CloseHandle (h);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize the process table.
|
/* Initialize the process table.
|
||||||
This is done once when the dll is first loaded. */
|
This is done once when the dll is first loaded. */
|
||||||
|
|
||||||
|
@ -96,6 +126,14 @@ pinfo_init (char **envp)
|
||||||
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
|
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_pinfo::exit (UINT n)
|
||||||
|
{
|
||||||
|
process_state = PID_EXITED;
|
||||||
|
sigproc_printf ("Calling ExitProcess %d", n);
|
||||||
|
ExitProcess (n);
|
||||||
|
}
|
||||||
|
|
||||||
struct sigaction&
|
struct sigaction&
|
||||||
_pinfo::getsig(int sig)
|
_pinfo::getsig(int sig)
|
||||||
{
|
{
|
||||||
|
@ -185,66 +223,82 @@ pinfo::init (pid_t n, DWORD create, HANDLE in_h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int created;
|
for (int i = 0; i < 10; i++)
|
||||||
char mapname[MAX_PATH];
|
|
||||||
__small_sprintf (mapname, "cygpid.%x", n);
|
|
||||||
|
|
||||||
int mapsize;
|
|
||||||
if (create & PID_EXECED)
|
|
||||||
mapsize = PINFO_REDIR_SIZE;
|
|
||||||
else
|
|
||||||
mapsize = sizeof (_pinfo);
|
|
||||||
|
|
||||||
if (in_h)
|
|
||||||
{
|
{
|
||||||
h = in_h;
|
int created;
|
||||||
created = 0;
|
char mapname[MAX_PATH];
|
||||||
}
|
__small_sprintf (mapname, "cygpid.%x", n);
|
||||||
else if (!create)
|
|
||||||
{
|
|
||||||
/* CGF FIXME -- deal with inheritance after an exec */
|
|
||||||
h = OpenFileMappingA (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapname);
|
|
||||||
created = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h = CreateFileMapping ((HANDLE) 0xffffffff, &sec_all_nih,
|
|
||||||
PAGE_READWRITE, 0, mapsize, mapname);
|
|
||||||
created = h && GetLastError () != ERROR_ALREADY_EXISTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!h)
|
int mapsize;
|
||||||
{
|
if (create & PID_EXECED)
|
||||||
if (create)
|
mapsize = PINFO_REDIR_SIZE;
|
||||||
__seterrno ();
|
else
|
||||||
procinfo = NULL;
|
mapsize = sizeof (_pinfo);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProtectHandle1 (h, pinfo_shared_handle);
|
if (in_h)
|
||||||
procinfo = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
{
|
||||||
|
h = in_h;
|
||||||
|
created = 0;
|
||||||
|
}
|
||||||
|
else if (!create)
|
||||||
|
{
|
||||||
|
/* CGF FIXME -- deal with inheritance after an exec */
|
||||||
|
h = OpenFileMappingA (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapname);
|
||||||
|
created = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h = CreateFileMapping ((HANDLE) 0xffffffff, &sec_all_nih,
|
||||||
|
PAGE_READWRITE, 0, mapsize, mapname);
|
||||||
|
created = h && GetLastError () != ERROR_ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
if (procinfo->process_state & PID_EXECED)
|
if (!h)
|
||||||
{
|
{
|
||||||
pid_t realpid = procinfo->pid;
|
if (create)
|
||||||
debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid);
|
__seterrno ();
|
||||||
release ();
|
procinfo = NULL;
|
||||||
if (realpid == n)
|
return;
|
||||||
api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
|
}
|
||||||
return init (realpid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (created)
|
procinfo = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||||
{
|
ProtectHandle1 (h, pinfo_shared_handle);
|
||||||
if (!(create & PID_EXECED))
|
|
||||||
|
if (procinfo->process_state & PID_EXECED)
|
||||||
|
{
|
||||||
|
assert (!i);
|
||||||
|
pid_t realpid = procinfo->pid;
|
||||||
|
debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid);
|
||||||
|
if (realpid == n)
|
||||||
|
api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
|
||||||
|
n = realpid;
|
||||||
|
release ();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In certain rare, pathological cases, it is possible for the shared
|
||||||
|
memory region to exist for a while after a process has exited. This
|
||||||
|
should only be a brief occurrence, so rather than introduce some kind
|
||||||
|
of locking mechanism, just loop. FIXME: I'm sure I'll regret doing it
|
||||||
|
this way at some point. */
|
||||||
|
if (i < 9 && !created && create && (procinfo->process_state & PID_EXITED))
|
||||||
|
{
|
||||||
|
Sleep (5);
|
||||||
|
release ();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!created)
|
||||||
|
/* nothing */;
|
||||||
|
else if (!(create & PID_EXECED))
|
||||||
procinfo->pid = n;
|
procinfo->pid = n;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
procinfo->pid = myself->pid;
|
procinfo->pid = myself->pid;
|
||||||
procinfo->process_state |= PID_IN_USE | PID_EXECED;
|
procinfo->process_state |= PID_IN_USE | PID_EXECED;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy = 1;
|
destroy = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,13 @@ public:
|
||||||
char root[MAX_PATH+1];
|
char root[MAX_PATH+1];
|
||||||
size_t rootlen;
|
size_t rootlen;
|
||||||
|
|
||||||
|
/* Resources used by process. */
|
||||||
|
long start_time;
|
||||||
|
struct rusage rusage_self;
|
||||||
|
struct rusage rusage_children;
|
||||||
|
/* Pointer to mmap'ed areas for this process. Set up by fork. */
|
||||||
|
void *mmap_ptr;
|
||||||
|
|
||||||
/* Non-zero if process was stopped by a signal. */
|
/* Non-zero if process was stopped by a signal. */
|
||||||
char stopsig;
|
char stopsig;
|
||||||
|
|
||||||
|
@ -104,21 +111,13 @@ public:
|
||||||
LONG* getsigtodo (int);
|
LONG* getsigtodo (int);
|
||||||
HANDLE getthread2signal ();
|
HANDLE getthread2signal ();
|
||||||
void setthread2signal (void *);
|
void setthread2signal (void *);
|
||||||
|
void exit (UINT n) __attribute__ ((noreturn));
|
||||||
/* Resources used by process. */
|
|
||||||
long start_time;
|
|
||||||
struct rusage rusage_self;
|
|
||||||
struct rusage rusage_children;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct sigaction sigs[NSIG];
|
struct sigaction sigs[NSIG];
|
||||||
sigset_t sig_mask; /* one set for everything to ignore. */
|
sigset_t sig_mask; /* one set for everything to ignore. */
|
||||||
LONG _sigtodo[NSIG + __SIGOFFSET];
|
LONG _sigtodo[NSIG + __SIGOFFSET];
|
||||||
ThreadItem* thread2signal; // NULL means means thread any other means a pthread
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class pinfo
|
class pinfo
|
||||||
|
@ -128,7 +127,7 @@ class pinfo
|
||||||
int destroy;
|
int destroy;
|
||||||
public:
|
public:
|
||||||
void init (pid_t n, DWORD create = 0, HANDLE h = NULL);
|
void init (pid_t n, DWORD create = 0, HANDLE h = NULL);
|
||||||
pinfo (): h (NULL), procinfo (0), destroy (0) {}
|
pinfo () {}
|
||||||
pinfo (_pinfo *x): procinfo (x) {}
|
pinfo (_pinfo *x): procinfo (x) {}
|
||||||
pinfo (pid_t n) {init (n);}
|
pinfo (pid_t n) {init (n);}
|
||||||
pinfo (pid_t n, int create) {init (n, create);}
|
pinfo (pid_t n, int create) {init (n, create);}
|
||||||
|
@ -181,7 +180,8 @@ extern pinfo myself;
|
||||||
extern "C" int _spawnve (HANDLE hToken, int mode, const char *path,
|
extern "C" int _spawnve (HANDLE hToken, int mode, const char *path,
|
||||||
const char *const *argv, const char *const *envp);
|
const char *const *argv, const char *const *envp);
|
||||||
|
|
||||||
extern void __stdcall exec_fixup_after_fork ();
|
extern void __stdcall pinfo_fixup_after_fork ();
|
||||||
|
extern void __stdcall pinfo_fixup_in_spawned_child (HANDLE hchild);
|
||||||
|
|
||||||
/* For mmaps across fork(). */
|
/* For mmaps across fork(). */
|
||||||
int __stdcall recreate_mmaps_after_fork (void *);
|
int __stdcall recreate_mmaps_after_fork (void *);
|
||||||
|
|
|
@ -65,6 +65,7 @@ fill_rusage (struct rusage *r, HANDLE h)
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
|
memset (r, 0, sizeof (*r));
|
||||||
GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time);
|
GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time);
|
||||||
totimeval (&tv, &kernel_time, 0, 0);
|
totimeval (&tv, &kernel_time, 0, 0);
|
||||||
add_timeval (&r->ru_stime, &tv);
|
add_timeval (&r->ru_stime, &tv);
|
||||||
|
|
|
@ -602,7 +602,6 @@ write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size)
|
||||||
int
|
int
|
||||||
set_process_privileges ()
|
set_process_privileges ()
|
||||||
{
|
{
|
||||||
HANDLE hProcess = NULL;
|
|
||||||
HANDLE hToken = NULL;
|
HANDLE hToken = NULL;
|
||||||
LUID restore_priv;
|
LUID restore_priv;
|
||||||
LUID backup_priv;
|
LUID backup_priv;
|
||||||
|
@ -610,14 +609,7 @@ set_process_privileges ()
|
||||||
TOKEN_PRIVILEGES *new_priv = (TOKEN_PRIVILEGES *) buf;
|
TOKEN_PRIVILEGES *new_priv = (TOKEN_PRIVILEGES *) buf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId ());
|
if (! OpenProcessToken (hMainProc,
|
||||||
if (! hProcess)
|
|
||||||
{
|
|
||||||
__seterrno ();
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! OpenProcessToken (hProcess,
|
|
||||||
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||||
&hToken))
|
&hToken))
|
||||||
{
|
{
|
||||||
|
@ -656,8 +648,6 @@ set_process_privileges ()
|
||||||
out:
|
out:
|
||||||
if (hToken)
|
if (hToken)
|
||||||
CloseHandle (hToken);
|
CloseHandle (hToken);
|
||||||
if (hProcess)
|
|
||||||
CloseHandle (hProcess);
|
|
||||||
|
|
||||||
syscall_printf ("%d = set_process_privileges ()", ret);
|
syscall_printf ("%d = set_process_privileges ()", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -19,6 +19,10 @@ details. */
|
||||||
#include "sigproc.h"
|
#include "sigproc.h"
|
||||||
#include "pinfo.h"
|
#include "pinfo.h"
|
||||||
|
|
||||||
|
int sigcatchers; /* FIXME: Not thread safe. */
|
||||||
|
|
||||||
|
#define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL)
|
||||||
|
|
||||||
extern "C" _sig_func_ptr
|
extern "C" _sig_func_ptr
|
||||||
signal (int sig, _sig_func_ptr func)
|
signal (int sig, _sig_func_ptr func)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +39,11 @@ signal (int sig, _sig_func_ptr func)
|
||||||
prev = myself->getsig (sig).sa_handler;
|
prev = myself->getsig (sig).sa_handler;
|
||||||
myself->getsig (sig).sa_handler = func;
|
myself->getsig (sig).sa_handler = func;
|
||||||
myself->getsig (sig).sa_mask = 0;
|
myself->getsig (sig).sa_mask = 0;
|
||||||
|
if (!sigtrapped (prev) && sigtrapped (func))
|
||||||
|
sigcatchers++;
|
||||||
|
else if (sigtrapped (prev) && !sigtrapped (func))
|
||||||
|
sigcatchers--;
|
||||||
|
|
||||||
syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
|
syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
@ -224,12 +233,8 @@ killpg (int pgrp, int sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
sigaction (int sig,
|
sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
|
||||||
const struct sigaction *newaction,
|
|
||||||
struct sigaction *oldaction)
|
|
||||||
{
|
{
|
||||||
struct sigaction out_oldaction;
|
|
||||||
|
|
||||||
/* check that sig is in right range */
|
/* check that sig is in right range */
|
||||||
if (sig < 0 || sig >= NSIG)
|
if (sig < 0 || sig >= NSIG)
|
||||||
{
|
{
|
||||||
|
@ -238,25 +243,28 @@ sigaction (int sig,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldaction)
|
struct sigaction oa = myself->getsig (sig);
|
||||||
out_oldaction = myself->getsig (sig);
|
|
||||||
|
|
||||||
if (newaction)
|
if (newact)
|
||||||
{
|
{
|
||||||
if ((sig == SIGKILL || sig == SIGSTOP) && newaction->sa_handler != SIG_DFL)
|
if ((sig == SIGKILL || sig == SIGSTOP) && newact->sa_handler != SIG_DFL)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
myself->getsig (sig) = *newaction;
|
myself->getsig (sig) = *newact;
|
||||||
if (newaction->sa_handler == SIG_IGN)
|
if (newact->sa_handler == SIG_IGN)
|
||||||
sig_clear (sig);
|
sig_clear (sig);
|
||||||
if (newaction->sa_handler == SIG_DFL && sig == SIGCHLD)
|
if (newact->sa_handler == SIG_DFL && sig == SIGCHLD)
|
||||||
sig_clear (sig);
|
sig_clear (sig);
|
||||||
|
if (!sigtrapped (oa.sa_handler) && sigtrapped (newact->sa_handler))
|
||||||
|
sigcatchers++;
|
||||||
|
else if (sigtrapped (oa.sa_handler) && !sigtrapped (newact->sa_handler))
|
||||||
|
sigcatchers--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldaction)
|
if (oldact)
|
||||||
*oldaction = out_oldaction;
|
*oldact = oa;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,8 @@ Static HANDLE wait_sig_inited = NULL; // Control synchronization of
|
||||||
*/
|
*/
|
||||||
Static HANDLE events[PSIZE + 1] = {0}; // All my children's handles++
|
Static HANDLE events[PSIZE + 1] = {0}; // All my children's handles++
|
||||||
#define hchildren (events + 1) // Where the children handles begin
|
#define hchildren (events + 1) // Where the children handles begin
|
||||||
Static pinfo pchildren[PSIZE] = {pinfo ()};// All my children info
|
Static pinfo pchildren[PSIZE]; // All my children info
|
||||||
Static pinfo zombies[PSIZE] = {pinfo ()}; // All my deceased children info
|
Static pinfo zombies[PSIZE]; // All my deceased children info
|
||||||
Static int nchildren = 0; // Number of active children
|
Static int nchildren = 0; // Number of active children
|
||||||
Static int nzombies = 0; // Number of deceased children
|
Static int nzombies = 0; // Number of deceased children
|
||||||
|
|
||||||
|
@ -195,18 +195,12 @@ pid_exists (pid_t pid)
|
||||||
return proc_exists (p);
|
return proc_exists (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test to determine if a process really exists and is processing
|
/* Test to determine if a process really exists and is processing signals.
|
||||||
* signals.
|
|
||||||
*/
|
*/
|
||||||
BOOL __stdcall
|
BOOL __stdcall
|
||||||
proc_exists (_pinfo *p)
|
proc_exists (_pinfo *p)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
return p && !(p->process_state & (PID_INITIALIZING | PID_EXITED));
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if this is one of our children, zero otherwise.
|
/* Return 1 if this is one of our children, zero otherwise.
|
||||||
|
@ -266,7 +260,7 @@ proc_subproc (DWORD what, DWORD val)
|
||||||
hchildren[nchildren] = vchild->hProcess;
|
hchildren[nchildren] = vchild->hProcess;
|
||||||
ProtectHandle1 (vchild->hProcess, childhProc);
|
ProtectHandle1 (vchild->hProcess, childhProc);
|
||||||
if (!DuplicateHandle (hMainProc, vchild->hProcess, hMainProc, &vchild->pid_handle,
|
if (!DuplicateHandle (hMainProc, vchild->hProcess, hMainProc, &vchild->pid_handle,
|
||||||
0, 0, DUPLICATE_SAME_ACCESS))
|
0, 0, DUPLICATE_SAME_ACCESS))
|
||||||
system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid);
|
system_printf ("Couldn't duplicate child handle for pid %d, %E", vchild->pid);
|
||||||
ProtectHandle1 (vchild->pid_handle, pid_handle);
|
ProtectHandle1 (vchild->pid_handle, pid_handle);
|
||||||
sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
|
sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
|
||||||
|
@ -301,11 +295,6 @@ proc_subproc (DWORD what, DWORD val)
|
||||||
zombies[nzombies] = pchildren[val]; // Add to zombie array
|
zombies[nzombies] = pchildren[val]; // Add to zombie array
|
||||||
zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead
|
zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead
|
||||||
remove_child (val); // Remove from children array
|
remove_child (val); // Remove from children array
|
||||||
if (!proc_loop_wait) // Don't bother if wait_subproc is
|
|
||||||
break; // exiting
|
|
||||||
|
|
||||||
/* Send a SIGCHLD to myself. */
|
|
||||||
rc = sig_send (myself_nowait, SIGCHLD); // Send a SIGCHLD
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* A child is in the stopped state. Scan wait() queue to see if anyone
|
/* A child is in the stopped state. Scan wait() queue to see if anyone
|
||||||
|
@ -445,15 +434,13 @@ proc_terminate (void)
|
||||||
ForceCloseHandle1 (zombies[i]->hProcess, childhProc);
|
ForceCloseHandle1 (zombies[i]->hProcess, childhProc);
|
||||||
ForceCloseHandle1 (zombies[i]->pid_handle, pid_handle);
|
ForceCloseHandle1 (zombies[i]->pid_handle, pid_handle);
|
||||||
}
|
}
|
||||||
zombies[i]->process_state = PID_NOT_IN_USE; /* CGF FIXME - still needed? */
|
zombies[i]->process_state = PID_EXITED; /* CGF FIXME - still needed? */
|
||||||
zombies[i].release(); // FIXME: this breaks older gccs for some reason
|
zombies[i].release(); // FIXME: this breaks older gccs for some reason
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disassociate my subprocesses */
|
/* Disassociate my subprocesses */
|
||||||
for (i = 0; i < nchildren; i++)
|
for (i = 0; i < nchildren; i++)
|
||||||
{
|
{
|
||||||
if (pchildren[i]->process_state == PID_NOT_IN_USE)
|
|
||||||
continue; // Should never happen
|
|
||||||
if (!pchildren[i]->hProcess)
|
if (!pchildren[i]->hProcess)
|
||||||
sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid,
|
sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid,
|
||||||
pchildren[i]->dwProcessId);
|
pchildren[i]->dwProcessId);
|
||||||
|
@ -596,10 +583,10 @@ sigproc_terminate (void)
|
||||||
ForceCloseHandle (sigcomplete_main);
|
ForceCloseHandle (sigcomplete_main);
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
(void) ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
|
(void) ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
|
||||||
ForceCloseHandle (sigcomplete_nonmain);
|
// ForceCloseHandle (sigcomplete_nonmain);
|
||||||
ForceCloseHandle (sigcatch_main);
|
// ForceCloseHandle (sigcatch_main);
|
||||||
ForceCloseHandle (sigcatch_nonmain);
|
// ForceCloseHandle (sigcatch_nonmain);
|
||||||
ForceCloseHandle (sigcatch_nosync);
|
// ForceCloseHandle (sigcatch_nosync);
|
||||||
}
|
}
|
||||||
proc_terminate (); // Terminate process handling thread
|
proc_terminate (); // Terminate process handling thread
|
||||||
|
|
||||||
|
@ -610,19 +597,19 @@ sigproc_terminate (void)
|
||||||
sigproc_printf ("entering");
|
sigproc_printf ("entering");
|
||||||
sig_loop_wait = 0; // Tell wait_sig to exit when it is
|
sig_loop_wait = 0; // Tell wait_sig to exit when it is
|
||||||
// finished with anything it is doing
|
// finished with anything it is doing
|
||||||
sig_dispatch_pending (TRUE); // wake up and die
|
// sig_dispatch_pending (TRUE); // wake up and die
|
||||||
|
/* In case of a sigsuspend */
|
||||||
|
SetEvent (signal_arrived);
|
||||||
|
|
||||||
/* If !hwait_sig, then the process probably hasn't even finished
|
/* If !hwait_sig, then the process probably hasn't even finished
|
||||||
* its initialization phase.
|
* its initialization phase.
|
||||||
*/
|
*/
|
||||||
if (hwait_sig)
|
if (0 && hwait_sig)
|
||||||
{
|
{
|
||||||
if (GetCurrentThreadId () != sigtid)
|
if (GetCurrentThreadId () != sigtid)
|
||||||
WaitForSingleObject (h, 10000);
|
WaitForSingleObject (h, 10000);
|
||||||
ForceCloseHandle1 (h, hwait_sig);
|
ForceCloseHandle1 (h, hwait_sig);
|
||||||
|
|
||||||
/* In case of a sigsuspend */
|
|
||||||
SetEvent (signal_arrived);
|
|
||||||
|
|
||||||
if (GetCurrentThreadId () != sigtid)
|
if (GetCurrentThreadId () != sigtid)
|
||||||
{
|
{
|
||||||
|
@ -636,9 +623,11 @@ sigproc_terminate (void)
|
||||||
sigproc_printf ("done");
|
sigproc_printf ("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Set this so that subsequent tests will succeed. */
|
/* Set this so that subsequent tests will succeed. */
|
||||||
if (!myself->dwProcessId)
|
if (!myself->dwProcessId)
|
||||||
myself->dwProcessId = GetCurrentProcessId ();
|
myself->dwProcessId = GetCurrentProcessId ();
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1128,7 +1117,7 @@ wait_sig (VOID *)
|
||||||
* Signalling subproc_ready indicates that we are a cygwin process.
|
* Signalling subproc_ready indicates that we are a cygwin process.
|
||||||
*/
|
*/
|
||||||
if (child_proc_info &&
|
if (child_proc_info &&
|
||||||
(child_proc_info->type == PROC_FORK || child_proc_info->type == PROC_SPAWN))
|
(child_proc_info->type == PROC_EXEC || child_proc_info->type == PROC_SPAWN))
|
||||||
{
|
{
|
||||||
debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
|
debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
|
||||||
if (!SetEvent (child_proc_info->subproc_ready))
|
if (!SetEvent (child_proc_info->subproc_ready))
|
||||||
|
@ -1144,13 +1133,6 @@ wait_sig (VOID *)
|
||||||
SetEvent (wait_sig_inited);
|
SetEvent (wait_sig_inited);
|
||||||
sigtid = GetCurrentThreadId ();
|
sigtid = GetCurrentThreadId ();
|
||||||
|
|
||||||
/* If we got something like a SIGINT while we were initializing, the
|
|
||||||
signal thread should be waiting for this event. This signals the
|
|
||||||
thread that it's ok to send the signal since the wait_sig thread
|
|
||||||
is now active. */
|
|
||||||
extern HANDLE console_handler_thread_waiter;
|
|
||||||
SetEvent (console_handler_thread_waiter);
|
|
||||||
|
|
||||||
HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
|
HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
|
||||||
sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId);
|
sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId);
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -1306,7 +1288,14 @@ wait_subproc (VOID *)
|
||||||
errloop = 0;
|
errloop = 0;
|
||||||
rc -= WAIT_OBJECT_0;
|
rc -= WAIT_OBJECT_0;
|
||||||
if (rc-- != 0)
|
if (rc-- != 0)
|
||||||
(void)proc_subproc (PROC_CHILDTERMINATED, rc);
|
{
|
||||||
|
(void) proc_subproc (PROC_CHILDTERMINATED, rc);
|
||||||
|
if (!proc_loop_wait) // Don't bother if wait_subproc is
|
||||||
|
break; // exiting
|
||||||
|
|
||||||
|
/* Send a SIGCHLD to myself. */
|
||||||
|
rc = sig_send (myself_nowait, SIGCHLD);
|
||||||
|
}
|
||||||
sigproc_printf ("looping");
|
sigproc_printf ("looping");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1327,7 +1316,6 @@ WFSO (HANDLE hHandle, DWORD dwMilliseconds)
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
sigframe thisframe (mainthread);
|
sigframe thisframe (mainthread);
|
||||||
ret = WaitForSingleObject (hHandle, dwMilliseconds);
|
ret = WaitForSingleObject (hHandle, dwMilliseconds);
|
||||||
if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,7 +1327,6 @@ WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
sigframe thisframe (mainthread);
|
sigframe thisframe (mainthread);
|
||||||
ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds);
|
ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds);
|
||||||
if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ struct sigthread
|
||||||
DWORD id;
|
DWORD id;
|
||||||
DWORD frame;
|
DWORD frame;
|
||||||
muto *lock;
|
muto *lock;
|
||||||
sigthread () : id (0), frame (0), lock (0) {}
|
|
||||||
void init (const char *s);
|
void init (const char *s);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -219,16 +219,6 @@ linebuf::prepend (const char *what, int len)
|
||||||
ix = newix;
|
ix = newix;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE hexec_proc = NULL;
|
|
||||||
|
|
||||||
void __stdcall
|
|
||||||
exec_fixup_after_fork ()
|
|
||||||
{
|
|
||||||
if (hexec_proc)
|
|
||||||
CloseHandle (hexec_proc);
|
|
||||||
hexec_proc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
class av
|
class av
|
||||||
{
|
{
|
||||||
char **argv;
|
char **argv;
|
||||||
|
@ -351,7 +341,7 @@ spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
|
||||||
}
|
}
|
||||||
|
|
||||||
ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
|
ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
|
||||||
ciresrv.moreinfo->old_title = old_title ? cstrdup (old_title) : NULL;
|
ciresrv.moreinfo->old_title = NULL;
|
||||||
ciresrv.moreinfo->fds = fdtab;
|
ciresrv.moreinfo->fds = fdtab;
|
||||||
ciresrv.moreinfo->nfds = fdtab.size;
|
ciresrv.moreinfo->nfds = fdtab.size;
|
||||||
|
|
||||||
|
@ -562,14 +552,6 @@ skip_arg_parsing:
|
||||||
if (!hToken && myself->token != INVALID_HANDLE_VALUE)
|
if (!hToken && myself->token != INVALID_HANDLE_VALUE)
|
||||||
hToken = myself->token;
|
hToken = myself->token;
|
||||||
|
|
||||||
/* FIXME: This leaves a handle to the process open so that the pid is not
|
|
||||||
duplicated. However, if a process execs another process two handles are
|
|
||||||
left open, which is unnecessary. */
|
|
||||||
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)
|
if (hToken)
|
||||||
{
|
{
|
||||||
/* allow the child to interact with our window station/desktop */
|
/* allow the child to interact with our window station/desktop */
|
||||||
|
@ -631,18 +613,18 @@ skip_arg_parsing:
|
||||||
seteuid (uid);
|
seteuid (uid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = CreateProcessA (real_path, /* image name - with full path */
|
rc = CreateProcess (real_path, /* image name - with full path */
|
||||||
one_line.buf, /* what was passed to exec */
|
one_line.buf, /* what was passed to exec */
|
||||||
/* process security attrs */
|
/* process security attrs */
|
||||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||||
/* thread security attrs */
|
/* thread security attrs */
|
||||||
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
|
||||||
TRUE, /* inherit handles from parent */
|
TRUE, /* inherit handles from parent */
|
||||||
flags,
|
flags,
|
||||||
envblock,/* environment */
|
envblock,/* environment */
|
||||||
0, /* use current drive/directory */
|
0, /* use current drive/directory */
|
||||||
&si,
|
&si,
|
||||||
&pi);
|
&pi);
|
||||||
|
|
||||||
MALLOC_CHECK;
|
MALLOC_CHECK;
|
||||||
if (envblock)
|
if (envblock)
|
||||||
|
@ -691,6 +673,7 @@ skip_arg_parsing:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
pinfo_fixup_in_spawned_child (pi.hProcess);
|
||||||
pinfo child (cygpid, 1);
|
pinfo child (cygpid, 1);
|
||||||
if (!child)
|
if (!child)
|
||||||
{
|
{
|
||||||
|
@ -859,6 +842,9 @@ skip_arg_parsing:
|
||||||
{
|
{
|
||||||
case _P_OVERLAY:
|
case _P_OVERLAY:
|
||||||
proc_terminate ();
|
proc_terminate ();
|
||||||
|
struct rusage r;
|
||||||
|
fill_rusage (&r, hMainProc);
|
||||||
|
add_rusage (&myself->rusage_self, &r);
|
||||||
ExitProcess (0);
|
ExitProcess (0);
|
||||||
break;
|
break;
|
||||||
case _P_WAIT:
|
case _P_WAIT:
|
||||||
|
|
|
@ -27,10 +27,8 @@ public:
|
||||||
void operator delete (void *) {;} /* can't handle allocated mutos
|
void operator delete (void *) {;} /* can't handle allocated mutos
|
||||||
currently */
|
currently */
|
||||||
|
|
||||||
/* This simple constructor is used for cases where no bruteforce
|
muto() {}
|
||||||
event handling is required. */
|
/* The real constructor. */
|
||||||
muto(): sync(0), visits(0), waiters(-1), bruteforce(0), tid(0), next (NULL) {;}
|
|
||||||
/* A more complicated constructor. */
|
|
||||||
muto(int inh, const char *name);
|
muto(int inh, const char *name);
|
||||||
~muto ();
|
~muto ();
|
||||||
int acquire (DWORD ms = INFINITE); /* Acquire the lock. */
|
int acquire (DWORD ms = INFINITE); /* Acquire the lock. */
|
||||||
|
|
|
@ -53,10 +53,16 @@ extern BOOL allow_ntsec;
|
||||||
void __stdcall
|
void __stdcall
|
||||||
close_all_files (void)
|
close_all_files (void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)fdtab.size; i++)
|
SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK," close");
|
||||||
if (!fdtab.not_open (i))
|
|
||||||
_close (i);
|
|
||||||
|
|
||||||
|
for (int i = 0; i < (int) fdtab.size; i++)
|
||||||
|
if (!fdtab.not_open (i))
|
||||||
|
{
|
||||||
|
fdtab[i]->close ();
|
||||||
|
fdtab.release (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK," close");
|
||||||
cygwin_shared->delqueue.process_queue ();
|
cygwin_shared->delqueue.process_queue ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +206,7 @@ extern "C" int
|
||||||
_read (int fd, void *ptr, size_t len)
|
_read (int fd, void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
sigframe thisframe (mainthread);
|
sigframe thisframe (mainthread);
|
||||||
|
extern int sigcatchers;
|
||||||
if (fdtab.not_open (fd))
|
if (fdtab.not_open (fd))
|
||||||
{
|
{
|
||||||
set_errno (EBADF);
|
set_errno (EBADF);
|
||||||
|
@ -211,10 +218,10 @@ _read (int fd, void *ptr, size_t len)
|
||||||
DWORD wait = (fh->get_flags () & (O_NONBLOCK | OLD_O_NDELAY)) ? 0 : INFINITE;
|
DWORD wait = (fh->get_flags () & (O_NONBLOCK | OLD_O_NDELAY)) ? 0 : INFINITE;
|
||||||
|
|
||||||
/* Could block, so let user know we at least got here. */
|
/* Could block, so let user know we at least got here. */
|
||||||
syscall_printf ("read (%d, %p, %d) %sblocking", fd, ptr, len, wait ? "" : "non");
|
syscall_printf ("read (%d, %p, %d) %sblocking, sigcatchers %d", fd, ptr, len, wait ? "" : "non", sigcatchers);
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
if (wait && (!fh->is_slow () || fh->get_r_no_interrupt ()))
|
if (wait && (!sigcatchers || !fh->is_slow () || fh->get_r_no_interrupt ()))
|
||||||
debug_printf ("non-interruptible read\n");
|
debug_printf ("non-interruptible read\n");
|
||||||
else if (!fh->ready_for_read (fd, wait, 0))
|
else if (!fh->ready_for_read (fd, wait, 0))
|
||||||
{
|
{
|
||||||
|
@ -236,7 +243,6 @@ _read (int fd, void *ptr, size_t len)
|
||||||
myself->process_state &= ~PID_TTYIN;
|
myself->process_state &= ~PID_TTYIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
syscall_printf ("%d = read (%d<%s>, %p, %d), errno %d", res, fd, fh->get_name (),
|
syscall_printf ("%d = read (%d<%s>, %p, %d), errno %d", res, fd, fh->get_name (),
|
||||||
ptr, len, get_errno ());
|
ptr, len, get_errno ());
|
||||||
|
@ -988,7 +994,7 @@ suffix_info stat_suffixes[] =
|
||||||
/* Cygwin internal */
|
/* Cygwin internal */
|
||||||
static int
|
static int
|
||||||
stat_worker (const char *caller, const char *name, struct stat *buf,
|
stat_worker (const char *caller, const char *name, struct stat *buf,
|
||||||
int nofollow)
|
int nofollow)
|
||||||
{
|
{
|
||||||
int res = -1;
|
int res = -1;
|
||||||
int oret = 1;
|
int oret = 1;
|
||||||
|
|
|
@ -29,7 +29,7 @@ extern "C"
|
||||||
#if defined (_CYG_THREAD_FAILSAFE) && defined (_MT_SAFE)
|
#if defined (_CYG_THREAD_FAILSAFE) && defined (_MT_SAFE)
|
||||||
void AssertResourceOwner (int, int);
|
void AssertResourceOwner (int, int);
|
||||||
#else
|
#else
|
||||||
#define AssertResourceOwner(i,ii)
|
# define AssertResourceOwner(i,ii)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,17 +126,17 @@ class pinfo;
|
||||||
class ResourceLocks
|
class ResourceLocks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ResourceLocks ():inited (false) {};
|
ResourceLocks () {};
|
||||||
LPCRITICAL_SECTION Lock (int);
|
LPCRITICAL_SECTION Lock (int);
|
||||||
void Init ();
|
void Init ();
|
||||||
void Delete ();
|
void Delete ();
|
||||||
#ifdef _CYG_THREAD_FAILSAFE
|
#ifdef _CYG_THREAD_FAILSAFE
|
||||||
DWORD owner;
|
DWORD owner;
|
||||||
DWORD count;
|
DWORD count;
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
CRITICAL_SECTION lock;
|
CRITICAL_SECTION lock;
|
||||||
bool inited;
|
bool inited;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,100 +146,99 @@ bool inited;
|
||||||
|
|
||||||
class MTitem
|
class MTitem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HANDLE win32_obj_id;
|
HANDLE win32_obj_id;
|
||||||
UINT return_value;
|
UINT return_value;
|
||||||
bool used;
|
bool used;
|
||||||
char joinable; // for thread only
|
char joinable; // for thread only
|
||||||
bool HandleOke () {return win32_obj_id;}
|
bool HandleOke () {return win32_obj_id;}
|
||||||
virtual void Destroy ();
|
virtual void Destroy ();
|
||||||
virtual int Id () {return (int) win32_obj_id;}
|
virtual int Id () {return (int) win32_obj_id;}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadItem:public MTitem
|
class ThreadItem: public MTitem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
TFD (function);
|
TFD (function);
|
||||||
void *arg;
|
void *arg;
|
||||||
void *return_ptr;
|
void *return_ptr;
|
||||||
bool suspended;
|
bool suspended;
|
||||||
DWORD thread_id;
|
DWORD thread_id;
|
||||||
DWORD GetThreadId () {return thread_id;}
|
DWORD GetThreadId () {return thread_id;}
|
||||||
|
|
||||||
/* signal handling */
|
/* signal handling */
|
||||||
struct sigaction *sigs;
|
struct sigaction *sigs;
|
||||||
sigset_t *sigmask;
|
sigset_t *sigmask;
|
||||||
LONG *sigtodo;
|
LONG *sigtodo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MutexItem:public MTitem
|
class MutexItem: public MTitem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int Lock ();
|
int Lock ();
|
||||||
int TryLock ();
|
int TryLock ();
|
||||||
int UnLock ();
|
int UnLock ();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SemaphoreItem:public MTitem
|
class SemaphoreItem: public MTitem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int shared;
|
int shared;
|
||||||
int Wait ();
|
int Wait ();
|
||||||
int Post ();
|
int Post ();
|
||||||
int TryWait ();
|
int TryWait ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MTitem *items[MT_MAX_ITEMS];
|
MTitem *items[MT_MAX_ITEMS];
|
||||||
int index;
|
int index;
|
||||||
}
|
} MTList;
|
||||||
MTList;
|
|
||||||
|
|
||||||
class MTinterface
|
class MTinterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// General
|
// General
|
||||||
DWORD reent_index;
|
DWORD reent_index;
|
||||||
DWORD thread_key;
|
DWORD thread_key;
|
||||||
|
|
||||||
// Used for main thread data, and sigproc thread
|
// Used for main thread data, and sigproc thread
|
||||||
struct __reent_t reents;
|
struct __reent_t reents;
|
||||||
struct _winsup_t winsup_reent;
|
struct _winsup_t winsup_reent;
|
||||||
ThreadItem mainthread;
|
ThreadItem mainthread;
|
||||||
|
|
||||||
void Init0 ();
|
void Init0 ();
|
||||||
void Init1 ();
|
void Init1 ();
|
||||||
void ClearReent ();
|
void ClearReent ();
|
||||||
|
|
||||||
void ReleaseItem (MTitem *);
|
void ReleaseItem (MTitem *);
|
||||||
|
|
||||||
// Thread functions
|
// Thread functions
|
||||||
ThreadItem *CreateThread (pthread_t *, TFD (func), void *, pthread_attr_t);
|
ThreadItem *CreateThread (pthread_t *, TFD (func), void *, pthread_attr_t);
|
||||||
ThreadItem *GetCallingThread ();
|
ThreadItem *GetCallingThread ();
|
||||||
ThreadItem *GetThread (pthread_t *);
|
ThreadItem *GetThread (pthread_t *);
|
||||||
|
|
||||||
// Mutex functions
|
// Mutex functions
|
||||||
MutexItem *CreateMutex (pthread_mutex_t *);
|
MutexItem *CreateMutex (pthread_mutex_t *);
|
||||||
MutexItem *GetMutex (pthread_mutex_t *);
|
MutexItem *GetMutex (pthread_mutex_t *);
|
||||||
|
|
||||||
// Semaphore functions
|
// Semaphore functions
|
||||||
SemaphoreItem *CreateSemaphore (sem_t *, int, int);
|
SemaphoreItem *CreateSemaphore (sem_t *, int, int);
|
||||||
SemaphoreItem *GetSemaphore (sem_t * t);
|
SemaphoreItem *GetSemaphore (sem_t * t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// General Administration
|
// General Administration
|
||||||
MTitem * Find (void *, int (*compare) (void *, void *), int &, MTList *);
|
MTitem * Find (void *, int (*compare) (void *, void *), int &, MTList *);
|
||||||
MTitem *GetItem (int, MTList *);
|
MTitem *GetItem (int, MTList *);
|
||||||
MTitem *SetItem (int, MTitem *, MTList *);
|
MTitem *SetItem (int, MTitem *, MTList *);
|
||||||
int Find (MTitem &, MTList *);
|
int Find (MTitem &, MTList *);
|
||||||
int FindNextUnused (MTList *);
|
int FindNextUnused (MTList *);
|
||||||
|
|
||||||
MTList threadlist;
|
MTList threadlist;
|
||||||
MTList mutexlist;
|
MTList mutexlist;
|
||||||
MTList semalist;
|
MTList semalist;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue