From 1dc16fc74bb91136d75b656f3a4aaefa87af9f20 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 15 Oct 2000 01:37:07 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 57 +++++++++++ winsup/cygwin/dcrt0.cc | 33 +++---- winsup/cygwin/debug.h | 10 ++ winsup/cygwin/exceptions.cc | 12 +-- winsup/cygwin/fork.cc | 7 +- winsup/cygwin/include/sys/cygwin.h | 4 +- winsup/cygwin/path.cc | 11 ++- winsup/cygwin/path.h | 2 +- winsup/cygwin/pinfo.cc | 150 ++++++++++++++++++++--------- winsup/cygwin/pinfo.h | 22 ++--- winsup/cygwin/resource.cc | 1 + winsup/cygwin/security.cc | 12 +-- winsup/cygwin/signal.cc | 36 ++++--- winsup/cygwin/sigproc.cc | 63 +++++------- winsup/cygwin/sigproc.h | 1 - winsup/cygwin/spawn.cc | 44 +++------ winsup/cygwin/sync.h | 6 +- winsup/cygwin/syscalls.cc | 20 ++-- winsup/cygwin/thread.h | 145 ++++++++++++++-------------- 19 files changed, 359 insertions(+), 277 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2e056877d..bdc040099 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,60 @@ +Sat Oct 14 21:24:16 2000 Christopher Faylor + + * 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 + + * 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 * cygwin.din: Add symbol hstrerror. diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 71775067f..5adf59478 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -683,8 +683,8 @@ dll_crt0_1 () cygheap_fixup_in_child (spawn_info->parent, 1); if (!spawn_info->moreinfo->myself_pinfo || !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo, - hMainProc, &h, 0, 0, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + hMainProc, &h, 0, 0, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) h = NULL; set_myself (mypid, h); __argc = spawn_info->moreinfo->argc; @@ -769,18 +769,6 @@ dll_crt0_1 () 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 */ dtable_init (); @@ -823,6 +811,18 @@ dll_crt0_1 () /* Set up __progname for getopt error call. */ __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; /* Call init of loaded dlls. */ dlls.init (); @@ -1057,9 +1057,8 @@ do_exit (int status) shared_terminate (); - sigproc_printf ("calling ExitProcess %d", n); minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n); - ExitProcess (n); + myself->exit (n); } extern "C" void @@ -1099,7 +1098,7 @@ __api_fatal (const char *fmt, ...) #ifdef DEBUGGING (void) try_to_debug (); #endif - ExitProcess (1); + myself->exit (1); } extern "C" { diff --git a/winsup/cygwin/debug.h b/winsup/cygwin/debug.h index d57ea4d0e..419cbab1b 100644 --- a/winsup/cygwin/debug.h +++ b/winsup/cygwin/debug.h @@ -16,12 +16,22 @@ details. */ #endif extern "C" { +#ifndef DEBUGGING0 DWORD __stdcall WFSO (HANDLE, 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 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_) #define _DEBUG_H_ diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 8d8178055..8a65f355b 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -47,7 +47,6 @@ static NO_COPY int exit_already = 0; static NO_COPY muto *mask_sync = NULL; HMODULE NO_COPY cygwin_hmodule; -HANDLE NO_COPY console_handler_thread_waiter = NULL; static const struct { @@ -126,10 +125,6 @@ set_console_handler () sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor = 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); if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE)) system_printf ("SetConsoleCtrlHandler failed, %E"); @@ -825,11 +820,6 @@ ctrl_c_handler (DWORD type) if (type == CTRL_LOGOFF_EVENT) 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)) /* Return FALSE to prevent an "End task" dialog box from appearing for each Cygwin process window that's open when the computer @@ -1005,7 +995,7 @@ signal_exit (int rc) { rc = EXIT_SIGNAL | (rc << 8); if (exit_already++) - ExitProcess (rc); + myself->exit (rc); /* 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 diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index a02e88b0a..c51fe23a3 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -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", myself->pid, myself->ppid, __builtin_frame_address (0)); - child_info_fork ch; - stack_base (ch); /* Restore the inheritance state as in parent 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); -debug_printf ("hParent %p", 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 char c; @@ -270,9 +267,9 @@ debug_printf ("hParent %p", hParent); MALLOC_CHECK; + pinfo_fixup_after_fork (); fdtab.fixup_after_fork (hParent); signal_fixup_after_fork (); - exec_fixup_after_fork (); MALLOC_CHECK; diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index 1c3c1e136..9bf3e62f9 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -66,7 +66,6 @@ typedef enum /* Flags associated with process_state */ enum { - PID_NOT_IN_USE = 0x0000, // Free entry. PID_IN_USE = 0x0001, // Entry in use. PID_ZOMBIE = 0x0002, // Child exited: no parent wait. PID_STOPPED = 0x0004, // Waiting for SIGCONT. @@ -86,7 +85,8 @@ enum // all execed or forked processes. PID_UNUSED2 = 0x2000, // child has execed 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 diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 5e4e2e97f..cfc81263a 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2396,8 +2396,8 @@ hash_path_name (unsigned long hash, const char *name) { char *nn, *newname = (char *) alloca (strlen (name) + 2); nn = strncpy (newname, name, 2); - if (islower (*nn)) - *newname = toupper (*nn); + if (isupper (*nn)) + *newname = tolower (*nn); *(nn += 2) = '\0'; name += 2; 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 referenced with an absolute value or relatively. */ - if (*name != '\\') + if (!hash && !isabspath (name)) { hash = cygcwd.get_hash (); if (name[0] == '.' && name[1] == '\0') 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. */ do { - hash += *name + (*name << 17); + int ch = tolower(*name); + hash += ch + (ch << 17); hash ^= hash >> 2; } while (*++name != '\0' && diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 3baa6a6cb..bef28fee9 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -12,7 +12,7 @@ struct suffix_info { const char *name; 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 diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 68f4923e7..8d037e3af 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -24,11 +24,41 @@ details. */ #include "perprocess.h" #include "environ.h" #include "security.h" +#include static char NO_COPY pinfo_dummy[sizeof(pinfo)] = {0}; 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. 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); } +void +_pinfo::exit (UINT n) +{ + process_state = PID_EXITED; + sigproc_printf ("Calling ExitProcess %d", n); + ExitProcess (n); +} + struct sigaction& _pinfo::getsig(int sig) { @@ -185,66 +223,82 @@ pinfo::init (pid_t n, DWORD create, HANDLE in_h) return; } - int created; - 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) + for (int i = 0; i < 10; i++) { - 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; - } + int created; + char mapname[MAX_PATH]; + __small_sprintf (mapname, "cygpid.%x", n); - if (!h) - { - if (create) - __seterrno (); - procinfo = NULL; - return; - } + int mapsize; + if (create & PID_EXECED) + mapsize = PINFO_REDIR_SIZE; + else + mapsize = sizeof (_pinfo); - ProtectHandle1 (h, pinfo_shared_handle); - procinfo = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (in_h) + { + 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) - { - pid_t realpid = procinfo->pid; - debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid); - release (); - if (realpid == n) - api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n); - return init (realpid); - } + if (!h) + { + if (create) + __seterrno (); + procinfo = NULL; + return; + } - if (created) - { - if (!(create & PID_EXECED)) + procinfo = (_pinfo *) MapViewOfFile (h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + ProtectHandle1 (h, pinfo_shared_handle); + + 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; else { procinfo->pid = myself->pid; procinfo->process_state |= PID_IN_USE | PID_EXECED; } + break; } - destroy = 1; } diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index bb1f2fe25..2c57d83c8 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -94,6 +94,13 @@ public: char root[MAX_PATH+1]; 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. */ char stopsig; @@ -104,21 +111,13 @@ public: LONG* getsigtodo (int); HANDLE getthread2signal (); void setthread2signal (void *); - - /* Resources used by process. */ - long start_time; - struct rusage rusage_self; - struct rusage rusage_children; + void exit (UINT n) __attribute__ ((noreturn)); 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; }; class pinfo @@ -128,7 +127,7 @@ class pinfo int destroy; public: 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 (pid_t n) {init (n);} 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, 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(). */ int __stdcall recreate_mmaps_after_fork (void *); diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc index 9ca19174a..58c2ced25 100644 --- a/winsup/cygwin/resource.cc +++ b/winsup/cygwin/resource.cc @@ -65,6 +65,7 @@ fill_rusage (struct rusage *r, HANDLE h) struct timeval tv; + memset (r, 0, sizeof (*r)); GetProcessTimes (h, &creation_time, &exit_time, &kernel_time, &user_time); totimeval (&tv, &kernel_time, 0, 0); add_timeval (&r->ru_stime, &tv); diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 044d85b8e..10379b66f 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -602,7 +602,6 @@ write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size) int set_process_privileges () { - HANDLE hProcess = NULL; HANDLE hToken = NULL; LUID restore_priv; LUID backup_priv; @@ -610,14 +609,7 @@ set_process_privileges () TOKEN_PRIVILEGES *new_priv = (TOKEN_PRIVILEGES *) buf; int ret = -1; - hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId ()); - if (! hProcess) - { - __seterrno (); - goto out; - } - - if (! OpenProcessToken (hProcess, + if (! OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { @@ -656,8 +648,6 @@ set_process_privileges () out: if (hToken) CloseHandle (hToken); - if (hProcess) - CloseHandle (hProcess); syscall_printf ("%d = set_process_privileges ()", ret); return ret; diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index d1ff1157c..afed39d6b 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -19,6 +19,10 @@ details. */ #include "sigproc.h" #include "pinfo.h" +int sigcatchers; /* FIXME: Not thread safe. */ + +#define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL) + extern "C" _sig_func_ptr signal (int sig, _sig_func_ptr func) { @@ -35,6 +39,11 @@ signal (int sig, _sig_func_ptr func) prev = myself->getsig (sig).sa_handler; myself->getsig (sig).sa_handler = func; 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); return prev; } @@ -224,12 +233,8 @@ killpg (int pgrp, int sig) } extern "C" int -sigaction (int sig, - const struct sigaction *newaction, - struct sigaction *oldaction) +sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact) { - struct sigaction out_oldaction; - /* check that sig is in right range */ if (sig < 0 || sig >= NSIG) { @@ -238,25 +243,28 @@ sigaction (int sig, return -1; } - if (oldaction) - out_oldaction = myself->getsig (sig); + struct sigaction oa = 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); return -1; } - myself->getsig (sig) = *newaction; - if (newaction->sa_handler == SIG_IGN) + myself->getsig (sig) = *newact; + if (newact->sa_handler == SIG_IGN) sig_clear (sig); - if (newaction->sa_handler == SIG_DFL && sig == SIGCHLD) + if (newact->sa_handler == SIG_DFL && sig == SIGCHLD) 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) - *oldaction = out_oldaction; + if (oldact) + *oldact = oa; return 0; } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 675feb4f3..1253b23eb 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -97,8 +97,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] = {pinfo ()};// All my children info -Static pinfo zombies[PSIZE] = {pinfo ()}; // All my deceased children info +Static pinfo pchildren[PSIZE]; // All my children info +Static pinfo zombies[PSIZE]; // All my deceased children info Static int nchildren = 0; // Number of active children Static int nzombies = 0; // Number of deceased children @@ -195,18 +195,12 @@ pid_exists (pid_t pid) return proc_exists (p); } -/* Test to determine if a process really exists and is processing - * signals. +/* Test to determine if a process really exists and is processing signals. */ BOOL __stdcall proc_exists (_pinfo *p) { - HANDLE h; - - if (p == NULL) - return FALSE; - else - return TRUE; + return p && !(p->process_state & (PID_INITIALIZING | PID_EXITED)); } /* 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; ProtectHandle1 (vchild->hProcess, childhProc); 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); ProtectHandle1 (vchild->pid_handle, pid_handle); 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++]->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 - - /* Send a SIGCHLD to myself. */ - rc = sig_send (myself_nowait, SIGCHLD); // Send a SIGCHLD break; /* 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]->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 } /* Disassociate my subprocesses */ for (i = 0; i < nchildren; i++) { - if (pchildren[i]->process_state == PID_NOT_IN_USE) - continue; // Should never happen if (!pchildren[i]->hProcess) sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid, pchildren[i]->dwProcessId); @@ -596,10 +583,10 @@ sigproc_terminate (void) ForceCloseHandle (sigcomplete_main); for (int i = 0; i < 20; i++) (void) ReleaseSemaphore (sigcomplete_nonmain, 1, NULL); - ForceCloseHandle (sigcomplete_nonmain); - ForceCloseHandle (sigcatch_main); - ForceCloseHandle (sigcatch_nonmain); - ForceCloseHandle (sigcatch_nosync); + // ForceCloseHandle (sigcomplete_nonmain); + // ForceCloseHandle (sigcatch_main); + // ForceCloseHandle (sigcatch_nonmain); + // ForceCloseHandle (sigcatch_nosync); } proc_terminate (); // Terminate process handling thread @@ -610,19 +597,19 @@ sigproc_terminate (void) sigproc_printf ("entering"); sig_loop_wait = 0; // Tell wait_sig to exit when it is // 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 * its initialization phase. */ - if (hwait_sig) + if (0 && hwait_sig) { if (GetCurrentThreadId () != sigtid) WaitForSingleObject (h, 10000); ForceCloseHandle1 (h, hwait_sig); - /* In case of a sigsuspend */ - SetEvent (signal_arrived); if (GetCurrentThreadId () != sigtid) { @@ -636,9 +623,11 @@ sigproc_terminate (void) sigproc_printf ("done"); } +#if 0 /* Set this so that subsequent tests will succeed. */ if (!myself->dwProcessId) myself->dwProcessId = GetCurrentProcessId (); +#endif return; } @@ -1128,7 +1117,7 @@ wait_sig (VOID *) * Signalling subproc_ready indicates that we are a cygwin process. */ 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); if (!SetEvent (child_proc_info->subproc_ready)) @@ -1144,13 +1133,6 @@ wait_sig (VOID *) SetEvent (wait_sig_inited); 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}; sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId); for (;;) @@ -1306,7 +1288,14 @@ wait_subproc (VOID *) errloop = 0; rc -= WAIT_OBJECT_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"); } @@ -1327,7 +1316,6 @@ WFSO (HANDLE hHandle, DWORD dwMilliseconds) DWORD ret; sigframe thisframe (mainthread); ret = WaitForSingleObject (hHandle, dwMilliseconds); -if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds); return ret; } @@ -1339,7 +1327,6 @@ WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds DWORD ret; sigframe thisframe (mainthread); ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds); -if (dwMilliseconds > 10 && ret == WAIT_TIMEOUT) system_printf ("TIMED OUT %d\n", dwMilliseconds); return ret; } } diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index aef272227..ee2e6a6cd 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -39,7 +39,6 @@ struct sigthread DWORD id; DWORD frame; muto *lock; - sigthread () : id (0), frame (0), lock (0) {} void init (const char *s); }; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 0aab714c1..6939ad578 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -219,16 +219,6 @@ linebuf::prepend (const char *what, int len) ix = newix; } -static HANDLE hexec_proc = NULL; - -void __stdcall -exec_fixup_after_fork () -{ - if (hexec_proc) - CloseHandle (hexec_proc); - hexec_proc = NULL; -} - class av { 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->old_title = old_title ? cstrdup (old_title) : NULL; + ciresrv.moreinfo->old_title = NULL; ciresrv.moreinfo->fds = fdtab; ciresrv.moreinfo->nfds = fdtab.size; @@ -562,14 +552,6 @@ skip_arg_parsing: if (!hToken && myself->token != INVALID_HANDLE_VALUE) 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) { /* allow the child to interact with our window station/desktop */ @@ -631,18 +613,18 @@ skip_arg_parsing: seteuid (uid); } else - rc = CreateProcessA (real_path, /* image name - with full path */ - one_line.buf, /* what was passed to exec */ + rc = CreateProcess (real_path, /* image name - with full path */ + one_line.buf, /* what was passed to exec */ /* process security attrs */ - allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, + allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, /* thread security attrs */ - allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, - TRUE, /* inherit handles from parent */ - flags, - envblock,/* environment */ - 0, /* use current drive/directory */ - &si, - &pi); + allow_ntsec ? sec_user (sa_buf) : &sec_all_nih, + TRUE, /* inherit handles from parent */ + flags, + envblock,/* environment */ + 0, /* use current drive/directory */ + &si, + &pi); MALLOC_CHECK; if (envblock) @@ -691,6 +673,7 @@ skip_arg_parsing: } else { + pinfo_fixup_in_spawned_child (pi.hProcess); pinfo child (cygpid, 1); if (!child) { @@ -859,6 +842,9 @@ skip_arg_parsing: { case _P_OVERLAY: proc_terminate (); + struct rusage r; + fill_rusage (&r, hMainProc); + add_rusage (&myself->rusage_self, &r); ExitProcess (0); break; case _P_WAIT: diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index f51ec9e62..32a2516c5 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -27,10 +27,8 @@ public: void operator delete (void *) {;} /* can't handle allocated mutos currently */ - /* This simple constructor is used for cases where no bruteforce - event handling is required. */ - muto(): sync(0), visits(0), waiters(-1), bruteforce(0), tid(0), next (NULL) {;} - /* A more complicated constructor. */ + muto() {} + /* The real constructor. */ muto(int inh, const char *name); ~muto (); int acquire (DWORD ms = INFINITE); /* Acquire the lock. */ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 65d439284..f54cc1ccf 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -53,10 +53,16 @@ extern BOOL allow_ntsec; void __stdcall close_all_files (void) { - for (int i = 0; i < (int)fdtab.size; i++) - if (!fdtab.not_open (i)) - _close (i); + SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK," close"); + 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 (); } @@ -200,6 +206,7 @@ extern "C" int _read (int fd, void *ptr, size_t len) { sigframe thisframe (mainthread); + extern int sigcatchers; if (fdtab.not_open (fd)) { 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; /* 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; - 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"); 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; } - out: syscall_printf ("%d = read (%d<%s>, %p, %d), errno %d", res, fd, fh->get_name (), ptr, len, get_errno ()); @@ -988,7 +994,7 @@ suffix_info stat_suffixes[] = /* Cygwin internal */ static int stat_worker (const char *caller, const char *name, struct stat *buf, - int nofollow) + int nofollow) { int res = -1; int oret = 1; diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index b285faa4f..0ef4725c5 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -29,7 +29,7 @@ extern "C" #if defined (_CYG_THREAD_FAILSAFE) && defined (_MT_SAFE) void AssertResourceOwner (int, int); #else -#define AssertResourceOwner(i,ii) +# define AssertResourceOwner(i,ii) #endif } @@ -126,17 +126,17 @@ class pinfo; class ResourceLocks { public: -ResourceLocks ():inited (false) {}; -LPCRITICAL_SECTION Lock (int); -void Init (); -void Delete (); + ResourceLocks () {}; + LPCRITICAL_SECTION Lock (int); + void Init (); + void Delete (); #ifdef _CYG_THREAD_FAILSAFE -DWORD owner; -DWORD count; + DWORD owner; + DWORD count; #endif -private: -CRITICAL_SECTION lock; -bool inited; + private: + CRITICAL_SECTION lock; + bool inited; }; @@ -146,100 +146,99 @@ bool inited; class MTitem { -public: -HANDLE win32_obj_id; -UINT return_value; -bool used; -char joinable; // for thread only -bool HandleOke () {return win32_obj_id;} -virtual void Destroy (); -virtual int Id () {return (int) win32_obj_id;} + public: + HANDLE win32_obj_id; + UINT return_value; + bool used; + char joinable; // for thread only + bool HandleOke () {return win32_obj_id;} + virtual void Destroy (); + virtual int Id () {return (int) win32_obj_id;} }; -class ThreadItem:public MTitem +class ThreadItem: public MTitem { public: -pthread_attr_t attr; -TFD (function); -void *arg; -void *return_ptr; -bool suspended; -DWORD thread_id; -DWORD GetThreadId () {return thread_id;} + pthread_attr_t attr; + TFD (function); + void *arg; + void *return_ptr; + bool suspended; + DWORD thread_id; + DWORD GetThreadId () {return thread_id;} -/* signal handling */ -struct sigaction *sigs; -sigset_t *sigmask; -LONG *sigtodo; + /* signal handling */ + struct sigaction *sigs; + sigset_t *sigmask; + LONG *sigtodo; }; -class MutexItem:public MTitem +class MutexItem: public MTitem { public: -int Lock (); -int TryLock (); -int UnLock (); + int Lock (); + int TryLock (); + int UnLock (); }; -class SemaphoreItem:public MTitem +class SemaphoreItem: public MTitem { public: -int shared; -int Wait (); -int Post (); -int TryWait (); + int shared; + int Wait (); + int Post (); + int TryWait (); }; typedef struct { -MTitem *items[MT_MAX_ITEMS]; -int index; -} -MTList; + MTitem *items[MT_MAX_ITEMS]; + int index; +} MTList; class MTinterface { public: -// General -DWORD reent_index; -DWORD thread_key; + // General + DWORD reent_index; + DWORD thread_key; -// Used for main thread data, and sigproc thread -struct __reent_t reents; -struct _winsup_t winsup_reent; -ThreadItem mainthread; + // Used for main thread data, and sigproc thread + struct __reent_t reents; + struct _winsup_t winsup_reent; + ThreadItem mainthread; -void Init0 (); -void Init1 (); -void ClearReent (); + void Init0 (); + void Init1 (); + void ClearReent (); -void ReleaseItem (MTitem *); + void ReleaseItem (MTitem *); -// Thread functions -ThreadItem *CreateThread (pthread_t *, TFD (func), void *, pthread_attr_t); -ThreadItem *GetCallingThread (); -ThreadItem *GetThread (pthread_t *); + // Thread functions + ThreadItem *CreateThread (pthread_t *, TFD (func), void *, pthread_attr_t); + ThreadItem *GetCallingThread (); + ThreadItem *GetThread (pthread_t *); -// Mutex functions -MutexItem *CreateMutex (pthread_mutex_t *); -MutexItem *GetMutex (pthread_mutex_t *); + // Mutex functions + MutexItem *CreateMutex (pthread_mutex_t *); + MutexItem *GetMutex (pthread_mutex_t *); -// Semaphore functions -SemaphoreItem *CreateSemaphore (sem_t *, int, int); -SemaphoreItem *GetSemaphore (sem_t * t); + // Semaphore functions + SemaphoreItem *CreateSemaphore (sem_t *, int, int); + SemaphoreItem *GetSemaphore (sem_t * t); private: -// General Administration -MTitem * Find (void *, int (*compare) (void *, void *), int &, MTList *); -MTitem *GetItem (int, MTList *); -MTitem *SetItem (int, MTitem *, MTList *); -int Find (MTitem &, MTList *); -int FindNextUnused (MTList *); + // General Administration + MTitem * Find (void *, int (*compare) (void *, void *), int &, MTList *); + MTitem *GetItem (int, MTList *); + MTitem *SetItem (int, MTitem *, MTList *); + int Find (MTitem &, MTList *); + int FindNextUnused (MTList *); -MTList threadlist; -MTList mutexlist; -MTList semalist; + MTList threadlist; + MTList mutexlist; + MTList semalist; };