diff options
author | cvs2svn <> | 2003-09-01 16:47:04 +0000 |
---|---|---|
committer | cvs2svn <> | 2003-09-01 16:47:04 +0000 |
commit | 2faac9e9f361dae261d6bf838321648816076061 (patch) | |
tree | 2f5f8a1b0d52c08bcc76299791878d4f3fa0f54c /winsup/cygwin | |
parent | 1910279d014b6b850d52c84d07c6e1bfb570e6e9 (diff) | |
download | newlib-cr-0x99.zip newlib-cr-0x99.tar.gz newlib-cr-0x99.tar.bz2 |
This commit was manufactured by cvs2svn to create tag 'cr-0x99'.cr-0x99
Sprout from Z-emcb-cygwin_daemon 2003-08-29 08:01:10 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'Z-emcb-'
Cherrypick from master 2003-09-01 16:47:03 UTC Christopher Faylor <me@cgf.cx> '* net.cc (dup_ent): Restore check for NULL input.':
winsup/cygserver/ChangeLog
winsup/cygserver/Makefile.in
winsup/cygserver/msg.cc
winsup/cygserver/sem.cc
winsup/cygserver/threaded_queue.h
winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/configure
winsup/cygwin/configure.in
winsup/cygwin/cygheap.cc
winsup/cygwin/cygheap.h
winsup/cygwin/dlmalloc.c
winsup/cygwin/dlmalloc.h
winsup/cygwin/exceptions.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/heap.cc
winsup/cygwin/include/sys/cygwin.h
winsup/cygwin/libc/fnmatch.c
winsup/cygwin/malloc.cc
winsup/cygwin/net.cc
winsup/cygwin/path.cc
winsup/cygwin/pinfo.h
winsup/cygwin/shm.cc
winsup/cygwin/signal.cc
winsup/cygwin/sigproc.cc
winsup/cygwin/sigproc.h
winsup/doc/ChangeLog
winsup/doc/pathnames.sgml
winsup/utils/ChangeLog
winsup/utils/Makefile.in
winsup/utils/kill.cc
Delete:
winsup/cygwin/cygserver.cc
winsup/cygwin/cygserver_client.cc
winsup/cygwin/cygserver_ipc.h
winsup/cygwin/cygserver_process.cc
winsup/cygwin/cygserver_shm.cc
winsup/cygwin/cygserver_shm.h
winsup/cygwin/cygserver_transport.cc
winsup/cygwin/cygserver_transport_pipes.cc
winsup/cygwin/cygserver_transport_sockets.cc
winsup/cygwin/threaded_queue.cc
winsup/cygwin/threaded_queue.h
Diffstat (limited to 'winsup/cygwin')
32 files changed, 397 insertions, 4497 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8810d54..3d4140a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,107 @@ +2003-09-01 Christopher Faylor <cgf@redhat.com> + + * net.cc (dup_ent): Restore check for NULL input. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * include/sys/cygwin.h: Don't define cygwin-specific things if + !__CYGWIN__. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * cygheap.cc (cygheap_init): Allocate space for sigaction array in + cygheap. + * cygheap.h (cygheap_types): Add HEAP_SIGS. + * exceptions.cc (signal_fixup_after_exec): Remove from this file. + * pinfo.h (pinfo::getsig): Just return global_sigs array. + (pinfo::sigs): Delete. + * sigproc.cc (signal_fixup_after_exec): Move it here. + (global_sigs): New global array, moved from pinfo structure. + (sigalloc): New function. Allocate global sigaction array here. + (proc_subproc): Remove copysigs call. It's automatic now. + * include/sys/cygwin.h (PID_NOCLDSTOP): New value. + * signal.cc (sigaction): Set myself->PID_NODCLDSTOP when appropriate. + * sigproc.h (sigalloc): Declare. + + * fnmatch.c (fnmatch): Use C90 parameters. + (rangematch): Ditto. + + * fhandler.cc (fhandler_base::raw_read): Use right coercion to avoid a + compiler warning. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * net.cc (dup_ent): Make debugging output consistent. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + Use dup_ent rather than specific dup_*_ptr functions throughout. + * (gen_ent): Delete. + (dup_ent): Subsume gen_ent functionality. + (dup_host_ptr): Delete. + (dup_proto_ptr): Ditto. + (dup_servent_ptr): Ditto. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * net.cc (gen_ent): Invert sense of null check so that debug output + makes sense. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * net.cc (free_char_list): Delete. + (dup_addr_list): Delete. + (dup_char_list): Delete. + (free_hostent_ptr): Delete. + (free_protoent_ptr): Delete. + (free_servent_ptr): Delete. + (DWORD_round): New function. + (strlen_round): New function. Returns strlen rounded up to word size. + (dup_ent): New, generic function to duplicate a {host,proto,serv}ent + structure. + (gen_ent): New macro. Generates a generic dup_{host,proto,serv}ent_ptr + function. + (cygwin_getservbyname): Remove call to free_servent_ptr, pass + servent_buf to dup_servent_ptr. + (cygwin_getservbyport): Ditto. + (cygwin_gethostbyname): Ditto for hostent. + (cygwin_gethostbyaddr): Ditto. + (cygwin_getprotobyname): Ditto for protoent. + (cygwin_getprotobynumber): Ditto. + +2003-08-31 Christopher Faylor <cgf@redhat.com> + + * Makefile.in (MALLOC_OFILES): Always fill in with correct malloc + object. + * configure.in: Fill in MALLOC_OFILES with either debugging or regular + malloc. + * configure: Regenerate. + * dlmalloc.c: Make various fruitless changes to attempt to get to work. + * dlmalloc.h: Ditto. + * malloc.cc (free): Check malloc pool when debugging. + + * path.cc (win32_device_name): Eliminate compiler warning. + + * sigproc.cc (sig_dispatch_pending): Remove use of was_pending. Let + thisframe.call_signal_handler decide if handler should be called rather + than using bogus was_pending check. + + * exceptions.cc (interrupt_setup): Remove accidentally checked in + debugging code. + +2003-08-30 Christopher Faylor <cgf@redhat.com> + + * heap.cc (sbrk): Save rounded addess in user_heap_max. + +2003-08-30 Christopher Faylor <cgf@redhat.com> + + * sigproc.cc (sig_dispatch_pending): Remove explicit call to + thisframe.call_signal_handler. + +2003-08-30 Christopher Faylor <cgf@redhat.com> + + Remove some cygserver files. + 2003-08-28 Christopher Faylor <cgf@redhat.com> * sigproc.h: Make some functions regparm. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 6a54a1c..41dad96 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -152,7 +152,7 @@ DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygthread.o dcrt0.o debug.o \ fhandler_socket.o fhandler_tape.o fhandler_termios.o \ fhandler_tty.o fhandler_virtual.o fhandler_windows.o \ fhandler_zero.o fnmatch.o fork.o glob.o grp.o heap.o init.o ioctl.o \ - ipc.o localtime.o malloc.o malloc_wrapper.o miscfuncs.o mmap.o msg.o \ + ipc.o localtime.o malloc_wrapper.o miscfuncs.o mmap.o msg.o \ net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o \ regcomp.o regerror.o regexec.o regfree.o registry.o resource.o \ scandir.o sched.o sec_acl.o sec_helper.o security.o select.o sem.o \ diff --git a/winsup/cygwin/configure b/winsup/cygwin/configure index 3500fad..eb1b688 100755 --- a/winsup/cygwin/configure +++ b/winsup/cygwin/configure @@ -1916,7 +1916,7 @@ esac fi -MALLOC_OFILES= +MALLOC_OFILES=malloc.o # Check whether --enable-malloc-debugging or --disable-malloc-debugging was given. if test "${enable_malloc_debugging+set}" = set; then enableval="$enable_malloc_debugging" diff --git a/winsup/cygwin/configure.in b/winsup/cygwin/configure.in index c0ad976..d47b408 100644 --- a/winsup/cygwin/configure.in +++ b/winsup/cygwin/configure.in @@ -145,7 +145,7 @@ no) LIBSERVER=;; esac ]) -MALLOC_OFILES= +MALLOC_OFILES=malloc.o AC_ARG_ENABLE(malloc-debugging, [ --enable-malloc-debugging Build a cygwin DLL with heap sanity checking (this is very slow, use only if you have heap corruption problems)], [case "${enableval}" in diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index c79b001..07151e9 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -22,6 +22,7 @@ #include "heap.h" #include "sync.h" #include "shared_info.h" +#include "sigproc.h" init_cygheap NO_COPY *cygheap; void NO_COPY *cygheap_max; @@ -203,6 +204,8 @@ cygheap_init () } if (!cygheap->fdtab) cygheap->fdtab.init (); + if (!cygheap->sigs) + sigalloc (); } /* Copyright (C) 1997, 2000 DJ Delorie */ diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 2211af2..7a637fa 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -17,6 +17,7 @@ enum cygheap_types HEAP_ARGV, HEAP_BUF, HEAP_MOUNT, + HEAP_SIGS, HEAP_1_START, HEAP_1_STR, HEAP_1_ARGV, @@ -255,6 +256,7 @@ struct init_cygheap #ifdef DEBUGGING cygheap_debug debug; #endif + struct sigaction *sigs; }; #define CYGHEAPSIZE (sizeof (init_cygheap) + (16000 * sizeof (fhandler_union)) + (5 * 65536)) diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc deleted file mode 100755 index 137730f..0000000 --- a/winsup/cygwin/cygserver.cc +++ /dev/null @@ -1,773 +0,0 @@ -/* cygserver.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Egor Duda <deo@logos-m.ru> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "woutsup.h" - -#include <sys/types.h> - -#include <assert.h> -#include <ctype.h> -#include <getopt.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "cygerrno.h" -#include "cygwin_version.h" - -#include "cygwin/cygserver.h" -#include "cygwin/cygserver_process.h" -#include "cygwin/cygserver_transport.h" - -// Version string. -static const char version[] = "$Revision$"; - -/* - * Support function for the XXX_printf () macros in "woutsup.h". - * Copied verbatim from "strace.cc". - */ -static int -getfunc (char *in_dst, const char *func) -{ - const char *p; - const char *pe; - char *dst = in_dst; - for (p = func; (pe = strchr (p, '(')); p = pe + 1) - if (isalnum ((int)pe[-1]) || pe[-1] == '_') - break; - else if (isspace ((int)pe[-1])) - { - pe--; - break; - } - if (!pe) - pe = strchr (func, '\0'); - for (p = pe; p > func; p--) - if (p != pe && *p == ' ') - { - p++; - break; - } - if (*p == '*') - p++; - while (p < pe) - *dst++ = *p++; - - *dst++ = ':'; - *dst++ = ' '; - *dst = '\0'; - - return dst - in_dst; -} - -/* - * Support function for the XXX_printf () macros in "woutsup.h". - */ -extern "C" void -__cygserver__printf (const char *const function, const char *const fmt, ...) -{ - const DWORD lasterror = GetLastError (); - const int lasterrno = errno; - - va_list ap; - - char *const buf = (char *) alloca (BUFSIZ); - - assert (buf); - - int len = 0; - - if (function) - len += getfunc (buf, function); - - va_start (ap, fmt); - len += vsnprintf (buf + len, BUFSIZ - len, fmt, ap); - va_end (ap); - - len += snprintf (buf + len, BUFSIZ - len, "\n"); - - const int actual = (len > BUFSIZ ? BUFSIZ : len); - - write (2, buf, actual); - - errno = lasterrno; - SetLastError (lasterror); - - return; -} - -#ifdef DEBUGGING - -int __stdcall -__set_errno (const char *func, int ln, int val) -{ - debug_printf ("%s:%d val %d", func, ln, val); - return _impure_ptr->_errno = val; -} - -#endif /* DEBUGGING */ - -GENERIC_MAPPING access_mapping; - -static BOOL -setup_privileges () -{ - BOOL rc, ret_val; - HANDLE hToken = NULL; - TOKEN_PRIVILEGES sPrivileges; - - rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ; - if (!rc) - { - system_printf ("error opening process token (%lu)", GetLastError ()); - ret_val = FALSE; - goto out; - } - rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid); - if (!rc) - { - system_printf ("error getting privilege luid (%lu)", GetLastError ()); - ret_val = FALSE; - goto out; - } - sPrivileges.PrivilegeCount = 1 ; - sPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; - rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ; - if (!rc) - { - system_printf ("error adjusting privilege level. (%lu)", - GetLastError ()); - ret_val = FALSE; - goto out; - } - - access_mapping.GenericRead = FILE_READ_DATA; - access_mapping.GenericWrite = FILE_WRITE_DATA; - access_mapping.GenericExecute = 0; - access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA; - - ret_val = TRUE; - -out: - CloseHandle (hToken); - return ret_val; -} - -int -check_and_dup_handle (HANDLE from_process, HANDLE to_process, - HANDLE from_process_token, - DWORD access, - HANDLE from_handle, - HANDLE *to_handle_ptr, BOOL bInheritHandle = FALSE) -{ - HANDLE local_handle = NULL; - int ret_val = EACCES; - - if (from_process != GetCurrentProcess ()) - { - if (!DuplicateHandle (from_process, from_handle, - GetCurrentProcess (), &local_handle, - 0, bInheritHandle, - DUPLICATE_SAME_ACCESS)) - { - system_printf ("error getting handle(%u) to server (%lu)", - (unsigned int)from_handle, GetLastError ()); - goto out; - } - } else - local_handle = from_handle; - - if (!wincap.has_security ()) - assert (!from_process_token); - else - { - char sd_buf [1024]; - PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) &sd_buf; - DWORD bytes_needed; - PRIVILEGE_SET ps; - DWORD ps_len = sizeof (ps); - BOOL status; - - if (!GetKernelObjectSecurity (local_handle, - (OWNER_SECURITY_INFORMATION - | GROUP_SECURITY_INFORMATION - | DACL_SECURITY_INFORMATION), - sd, sizeof (sd_buf), &bytes_needed)) - { - system_printf ("error getting handle SD (%lu)", GetLastError ()); - goto out; - } - - MapGenericMask (&access, &access_mapping); - - if (!AccessCheck (sd, from_process_token, access, &access_mapping, - &ps, &ps_len, &access, &status)) - { - system_printf ("error checking access rights (%lu)", - GetLastError ()); - goto out; - } - - if (!status) - { - system_printf ("access to object denied"); - goto out; - } - } - - if (!DuplicateHandle (from_process, from_handle, - to_process, to_handle_ptr, - access, bInheritHandle, 0)) - { - system_printf ("error getting handle to client (%lu)", GetLastError ()); - goto out; - } - - // verbose: debug_printf ("Duplicated %p to %p", from_handle, *to_handle_ptr); - - ret_val = 0; - - out: - if (local_handle && from_process != GetCurrentProcess ()) - CloseHandle (local_handle); - - return (ret_val); -} - -/* - * client_request_attach_tty::serve () - */ - -void -client_request_attach_tty::serve (transport_layer_base *const conn, - process_cache *) -{ - assert (conn); - - assert (!error_code ()); - - if (!wincap.has_security ()) - { - syscall_printf ("operation only supported on systems with security"); - error_code (EINVAL); - msglen (0); - return; - } - - if (msglen () != sizeof (req)) - { - syscall_printf ("bad request body length: expecting %lu bytes, got %lu", - sizeof (req), msglen ()); - error_code (EINVAL); - msglen (0); - return; - } - - msglen (0); // Until we fill in some fields. - - // verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld", - // req.master_pid, req.from_master, req.to_master, - // req.pid); - - // verbose: debug_printf ("opening process %ld", req.master_pid); - - const HANDLE from_process_handle = - OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid); - - if (!from_process_handle) - { - system_printf ("error opening `from' process, error = %lu", - GetLastError ()); - error_code (EACCES); - return; - } - - // verbose: debug_printf ("opening process %ld", req.pid); - - const HANDLE to_process_handle = - OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid); - - if (!to_process_handle) - { - system_printf ("error opening `to' process, error = %lu", - GetLastError ()); - CloseHandle (from_process_handle); - error_code (EACCES); - return; - } - - // verbose: debug_printf ("Impersonating client"); - conn->impersonate_client (); - - HANDLE token_handle = NULL; - - // verbose: debug_printf ("about to open thread token"); - const DWORD rc = OpenThreadToken (GetCurrentThread (), - TOKEN_QUERY, - TRUE, - &token_handle); - - // verbose: debug_printf ("opened thread token, rc=%lu", rc); - conn->revert_to_self (); - - if (!rc) - { - system_printf ("error opening thread token, error = %lu", - GetLastError ()); - CloseHandle (from_process_handle); - CloseHandle (to_process_handle); - error_code (EACCES); - return; - } - - // From this point on, a reply body is returned to the client. - - const HANDLE from_master = req.from_master; - const HANDLE to_master = req.to_master; - - req.from_master = NULL; - req.to_master = NULL; - - msglen (sizeof (req)); - - if (from_master) - if (check_and_dup_handle (from_process_handle, to_process_handle, - token_handle, - GENERIC_READ, - from_master, - &req.from_master, TRUE) != 0) - { - system_printf ("error duplicating from_master handle, error = %lu", - GetLastError ()); - error_code (EACCES); - } - - if (to_master) - if (check_and_dup_handle (from_process_handle, to_process_handle, - token_handle, - GENERIC_WRITE, - to_master, - &req.to_master, TRUE) != 0) - { - system_printf ("error duplicating to_master handle, error = %lu", - GetLastError ()); - error_code (EACCES); - } - - CloseHandle (from_process_handle); - CloseHandle (to_process_handle); - CloseHandle (token_handle); - - debug_printf ("%lu(%lu, %lu) -> %lu(%lu,%lu)", - req.master_pid, from_master, to_master, - req.pid, req.from_master, req.to_master); - - return; -} - -void -client_request_get_version::serve (transport_layer_base *, process_cache *) -{ - assert (!error_code ()); - - if (msglen ()) - syscall_printf ("unexpected request body ignored: %lu bytes", msglen ()); - - msglen (sizeof (version)); - - version.major = CYGWIN_SERVER_VERSION_MAJOR; - version.api = CYGWIN_SERVER_VERSION_API; - version.minor = CYGWIN_SERVER_VERSION_MINOR; - version.patch = CYGWIN_SERVER_VERSION_PATCH; -} - -class server_request : public queue_request -{ -public: - server_request (transport_layer_base *const conn, process_cache *const cache) - : _conn (conn), _cache (cache) - {} - - virtual ~server_request () - { - safe_delete (_conn); - } - - virtual void process () - { - client_request::handle_request (_conn, _cache); - } - -private: - transport_layer_base *const _conn; - process_cache *const _cache; -}; - -class server_submission_loop : public queue_submission_loop -{ -public: - server_submission_loop (threaded_queue *const queue, - transport_layer_base *const transport, - process_cache *const cache) - : queue_submission_loop (queue, false), - _transport (transport), - _cache (cache) - { - assert (_transport); - assert (_cache); - } - -private: - transport_layer_base *const _transport; - process_cache *const _cache; - - virtual void request_loop (); -}; - -/* FIXME: this is a little ugly. What we really want is to wait on - * two objects: one for the pipe/socket, and one for being told to - * shutdown. Otherwise this will stay a problem (we won't actually - * shutdown until the request _AFTER_ the shutdown request. And - * sending ourselves a request is ugly - */ -void -server_submission_loop::request_loop () -{ - /* I'd like the accepting thread's priority to be above any "normal" - * thread in the system to avoid overflowing the listen queue (for - * sockets; similar issues exist for named pipes); but, for example, - * a normal priority thread in a foregrounded process is boosted to - * THREAD_PRIORITY_HIGHEST (AFAICT). Thus try to set the current - * thread's priority to a level one above that. This fails on - * win9x/ME so assume any failure in that call is due to that and - * simply call again at one priority level lower. - */ - if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1)) - if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST)) - debug_printf ("failed to raise accept thread priority, error = %lu", - GetLastError ()); - - while (_running) - { - bool recoverable = false; - transport_layer_base *const conn = _transport->accept (&recoverable); - if (!conn && !recoverable) - { - system_printf ("fatal error on IPC transport: closing down"); - return; - } - // EINTR probably implies a shutdown request; so back off for a - // moment to let the main thread take control, otherwise the - // server spins here receiving EINTR repeatedly since the signal - // handler in the main thread doesn't get a chance to be called. - if (!conn && errno == EINTR) - { - if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL)) - debug_printf ("failed to reset thread priority, error = %lu", - GetLastError ()); - - Sleep (0); - if (!SetThreadPriority (GetCurrentThread (), - THREAD_PRIORITY_HIGHEST + 1)) - if (!SetThreadPriority (GetCurrentThread (), - THREAD_PRIORITY_HIGHEST)) - debug_printf ("failed to raise thread priority, error = %lu", - GetLastError ()); - } - if (conn) - _queue->add (safe_new (server_request, conn, _cache)); - } -} - -client_request_shutdown::client_request_shutdown () - : client_request (CYGSERVER_REQUEST_SHUTDOWN) -{ - // verbose: syscall_printf ("created"); -} - -void -client_request_shutdown::serve (transport_layer_base *, process_cache *) -{ - assert (!error_code ()); - - if (msglen ()) - syscall_printf ("unexpected request body ignored: %lu bytes", msglen ()); - - /* FIXME: link upwards, and then this becomes a trivial method call to - * only shutdown _this queue_ - */ - - kill (getpid (), SIGINT); - - msglen (0); -} - -static sig_atomic_t shutdown_server = false; - -static void -handle_signal (const int signum) -{ - /* any signal makes us die :} */ - - shutdown_server = true; -} - -/* - * print_usage () - */ - -static void -print_usage (const char *const pgm) -{ - printf ("Usage: %s [OPTIONS]\n", pgm); - printf (" -c, --cleanup-threads number of cleanup threads to use\n"); - printf (" -h, --help output usage information and exit\n"); - printf (" -r, --request-threads number of request threads to use\n"); - printf (" -s, --shutdown shutdown the daemon\n"); - printf (" -v, --version output version information and exit\n"); -} - -/* - * print_version () - */ - -static void -print_version (const char *const pgm) -{ - char *vn = NULL; - - const char *const colon = strchr (version, ':'); - - if (!colon) - { - vn = strdup ("?"); - } - else - { - vn = strdup (colon + 2); // Skip ": " - - char *const spc = strchr (vn, ' '); - - if (spc) - *spc = '\0'; - } - - char buf[200]; - snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s", - cygwin_version.dll_major / 1000, - cygwin_version.dll_major % 1000, - cygwin_version.dll_minor, - cygwin_version.api_major, - cygwin_version.api_minor, - cygwin_version.shared_data, - CYGWIN_SERVER_VERSION_MAJOR, - CYGWIN_SERVER_VERSION_API, - CYGWIN_SERVER_VERSION_MINOR, - CYGWIN_SERVER_VERSION_PATCH, - cygwin_version.mount_registry, - cygwin_version.dll_build_date); - - printf ("%s (cygwin) %s\n", pgm, vn); - printf ("API version %s\n", buf); - printf ("Copyright 2001, 2002 Red Hat, Inc.\n"); - printf ("Compiled on %s\n", __DATE__); - - free (vn); -} - -/* - * main () - */ - -int -main (const int argc, char *argv[]) -{ - const struct option longopts[] = { - {"cleanup-threads", required_argument, NULL, 'c'}, - {"help", no_argument, NULL, 'h'}, - {"request-threads", required_argument, NULL, 'r'}, - {"shutdown", no_argument, NULL, 's'}, - {"version", no_argument, NULL, 'v'}, - {0, no_argument, NULL, 0} - }; - - const char opts[] = "c:hr:sv"; - - int cleanup_threads = 2; - int request_threads = 10; - bool shutdown = false; - - const char *pgm = NULL; - - if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/'))) - pgm = *argv; - else - pgm++; - - wincap.init (); - if (wincap.has_security ()) - setup_privileges (); - - int opt; - - while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF) - switch (opt) - { - case 'c': - cleanup_threads = atoi (optarg); - if (cleanup_threads <= 0) - { - fprintf (stderr, - "%s: number of cleanup threads must be positive\n", - pgm); - exit (1); - } - break; - - case 'h': - print_usage (pgm); - return 0; - - case 'r': - request_threads = atoi (optarg); - if (request_threads <= 0) - { - fprintf (stderr, - "%s: number of request threads must be positive\n", - pgm); - exit (1); - } - break; - - case 's': - shutdown = true; - break; - - case 'v': - print_version (pgm); - return 0; - - case '?': - fprintf (stderr, "Try `%s --help' for more information.\n", pgm); - exit (1); - } - - if (optind != argc) - { - fprintf (stderr, "%s: too many arguments\n", pgm); - exit (1); - } - - if (shutdown) - { - /* Setting `cygserver_running' stops the request code making a - * version request, which is not much to the point. - */ - cygserver_running = CYGSERVER_OK; - - client_request_shutdown req; - - if (req.make_request () == -1 || req.error_code ()) - { - fprintf (stderr, "%s: shutdown request failed: %s\n", - pgm, strerror (req.error_code ())); - exit (1); - } - - // FIXME: It would be nice to wait here for the daemon to exit. - - return 0; - } - -#define SIGHANDLE(SIG) \ - do \ - { \ - struct sigaction act; \ - \ - act.sa_handler = &handle_signal; \ - act.sa_mask = 0; \ - act.sa_flags = 0; \ - \ - if (sigaction (SIG, &act, NULL) == -1) \ - { \ - system_printf ("failed to install handler for " #SIG ": %s", \ - strerror (errno)); \ - exit (1); \ - } \ - } while (false) - - SIGHANDLE (SIGHUP); - SIGHANDLE (SIGINT); - SIGHANDLE (SIGTERM); - - print_version (pgm); - setbuf (stdout, NULL); - printf ("daemon starting up"); - - threaded_queue request_queue (request_threads); - printf ("."); - - transport_layer_base *const transport = create_server_transport (); - assert (transport); - printf ("."); - - process_cache cache (cleanup_threads); - printf ("."); - - server_submission_loop submission_loop (&request_queue, transport, &cache); - printf ("."); - - request_queue.add_submission_loop (&submission_loop); - printf ("."); - - if (transport->listen () == -1) - { - exit (1); - } - printf ("."); - - cache.start (); - printf ("."); - - request_queue.start (); - printf ("."); - - printf ("complete\n"); - - /* TODO: wait on multiple objects - the thread handle for each - * request loop + all the process handles. This should be done by - * querying the request_queue and the process cache for all their - * handles, and then waiting for (say) 30 seconds. after that we - * recreate the list of handles to wait on, and wait again. the - * point of all this abstraction is that we can trivially server - * both sockets and pipes simply by making a new transport, and then - * calling request_queue.process_requests (transport2); - */ - /* WaitForMultipleObjects abort && request_queue && process_queue && signal - -- if signal event then retrigger it - */ - while (!shutdown_server && request_queue.running () && cache.running ()) - pause (); - - printf ("\nShutdown request received - new requests will be denied\n"); - request_queue.stop (); - printf ("All pending requests processed\n"); - safe_delete (transport); - printf ("No longer accepting requests - cygwin will operate in daemonless mode\n"); - cache.stop (); - printf ("All outstanding process-cache activities completed\n"); - printf ("daemon shutdown\n"); - - return 0; -} diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc deleted file mode 100755 index f668318..0000000 --- a/winsup/cygwin/cygserver_client.cc +++ /dev/null @@ -1,528 +0,0 @@ -/* cygserver_client.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Egor Duda <deo@logos-m.ru> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifdef __OUTSIDE_CYGWIN__ -#include "woutsup.h" -#else -#include "winsup.h" -#endif - -#include <assert.h> -#include <stdio.h> -#include <unistd.h> - -#include "cygerrno.h" -#include "cygserver_shm.h" -#include "safe_memory.h" - -#include "cygwin/cygserver.h" -#include "cygwin/cygserver_transport.h" - -int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children. - -/* On by default during development. For release, we probably want off - * by default. - */ -bool allow_daemon = true; // Nb: inherited by children. - -client_request_get_version::client_request_get_version () - : client_request (CYGSERVER_REQUEST_GET_VERSION, &version, sizeof (version)) -{ - msglen (0); // No parameters for request. - - // verbose: syscall_printf ("created"); -} - -/* - * client_request_get_version::check_version () - * - * The major version and API version numbers must match exactly. An - * older than expected minor version number is accepted (as long as - * the first numbers match, that is). - */ - -bool -client_request_get_version::check_version () const -{ - const bool ok = (version.major == CYGWIN_SERVER_VERSION_MAJOR - && version.api == CYGWIN_SERVER_VERSION_API - && version.minor <= CYGWIN_SERVER_VERSION_MINOR); - - if (!ok) - syscall_printf (("incompatible version of cygwin server: " - "client version %d.%d.%d.%d, " - "server version %ld.%ld.%ld.%ld"), - CYGWIN_SERVER_VERSION_MAJOR, - CYGWIN_SERVER_VERSION_API, - CYGWIN_SERVER_VERSION_MINOR, - CYGWIN_SERVER_VERSION_PATCH, - version.major, - version.api, - version.minor, - version.patch); - - return ok; -} - -#ifdef __INSIDE_CYGWIN__ - -client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid, - HANDLE nfrom_master, - HANDLE nto_master) - : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req)) -{ - req.pid = GetCurrentProcessId (); - req.master_pid = nmaster_pid; - req.from_master = nfrom_master; - req.to_master = nto_master; - - syscall_printf (("created: pid = %lu, master_pid = %lu, " - "from_master = %lu, to_master = %lu"), - req.pid, req.master_pid, req.from_master, req.to_master); -} - -#else /* !__INSIDE_CYGWIN__ */ - -client_request_attach_tty::client_request_attach_tty () - : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req)) -{ - // verbose: syscall_printf ("created"); -} - -#endif /* __INSIDE_CYGWIN__ */ - -/* - * client_request_attach_tty::send () - * - * Wraps the base method to provide error handling support. If the - * reply contains a body but is flagged as an error, close any handles - * that have been returned by cygserver and then discard the message - * body, i.e. the client either sees a successful result with handles - * or an unsuccessful result with no handles. - */ - -void -client_request_attach_tty::send (transport_layer_base * const conn) -{ - client_request::send (conn); - - if (msglen () && error_code ()) - { - if (from_master ()) - CloseHandle (from_master ()); - if (to_master ()) - CloseHandle (to_master ()); - msglen (0); - } -} - -client_request::header_t::header_t (const request_code_t request_code, - const size_t msglen) - : msglen (msglen), - request_code (request_code) -{ - assert (request_code >= 0 && request_code < CYGSERVER_REQUEST_LAST); -} - -// FIXME: also check write and read result for -1. - -void -client_request::send (transport_layer_base * const conn) -{ - assert (conn); - assert (!(msglen () && !_buf)); // i.e., msglen () implies _buf - assert (msglen () <= _buflen); - - { - const ssize_t count = conn->write (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("request header write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen ()) - { - const ssize_t count = conn->write (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("request body write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("request sent (%ld + %ld bytes)", - // sizeof (_header), msglen ()); - - { - const ssize_t count = conn->read (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("reply header read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen () && !_buf) - { - system_printf ("no client buffer for reply body: %ld bytes needed", - msglen ()); - error_code (EINVAL); - return; - } - - if (msglen () > _buflen) - { - system_printf (("client buffer too small for reply body: " - "have %ld bytes and need %ld"), - _buflen, msglen ()); - error_code (EINVAL); - return; - } - - if (msglen ()) - { - const ssize_t count = conn->read (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("reply body read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("reply received (%ld + %ld bytes)", - // sizeof (_header), msglen ()); -} - -#ifndef __INSIDE_CYGWIN__ - -/* - * client_request::handle_request () - * - * A server-side method. - * - * This is a factory method for the client_request subclasses. It - * reads the incoming request header and, based on its request code, - * creates an instance of the appropriate class. - * - * FIXME: If the incoming packet is malformed, the server drops it on - * the floor. Should it try and generate some sort of reply for the - * client? As it is, the client will simply get a broken connection. - * - * FIXME: also check write and read result for -1. - */ - -/* static */ void -client_request::handle_request (transport_layer_base *const conn, - process_cache *const cache) -{ - // verbose: debug_printf ("about to read"); - - header_t header; - - { - const ssize_t count = conn->read (&header, sizeof (header)); - - if (count != sizeof (header)) - { - syscall_printf (("request header read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, sizeof (header), - errno, GetLastError ()); - return; - } - - // verbose: debug_printf ("got header (%ld)", count); - } - - client_request *req = NULL; - - switch (header.request_code) - { - case CYGSERVER_REQUEST_GET_VERSION: - req = safe_new0 (client_request_get_version); - break; - case CYGSERVER_REQUEST_SHUTDOWN: - req = safe_new0 (client_request_shutdown); - break; - case CYGSERVER_REQUEST_ATTACH_TTY: - req = safe_new0 (client_request_attach_tty); - break; - case CYGSERVER_REQUEST_SHM: - req = safe_new0 (client_request_shm); - break; - default: - syscall_printf ("unknown request code %d received: request ignored", - header.request_code); - return; - } - - assert (req); - - req->msglen (header.msglen); - req->handle (conn, cache); - - safe_delete (req); - -#ifndef DEBUGGING - printf ("."); // A little noise when we're being quiet. -#endif -} - -#endif /* !__INSIDE_CYGWIN__ */ - -client_request::client_request (request_code_t const id, - void * const buf, - size_t const buflen) - : _header (id, buflen), - _buf (buf), - _buflen (buflen) -{ - assert ((!_buf && !_buflen) || (_buf && _buflen)); -} - -client_request::~client_request () -{} - -int -client_request::make_request () -{ - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - if (cygserver_running == CYGSERVER_UNKNOWN) - cygserver_init (); - - assert (cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - /* Don't retry every request if the server's not there */ - if (cygserver_running == CYGSERVER_UNAVAIL) - { - syscall_printf ("cygserver un-available"); - error_code (ENOSYS); - return -1; - } - - transport_layer_base *const transport = create_server_transport (); - - assert (transport); - - if (transport->connect () == -1) - { - if (errno) - error_code (errno); - else - error_code (ENOSYS); - safe_delete (transport); - return -1; - } - - // verbose: debug_printf ("connected to server %p", transport); - - send (transport); - - safe_delete (transport); - - return 0; -} - -#ifndef __INSIDE_CYGWIN__ - -/* - * client_request::handle () - * - * A server-side method. - * - * At this point, the header of an incoming request has been read and - * an appropriate client_request object constructed. This method has - * to read the request body into its buffer, if there is such a body, - * then perform the request and send back the results to the client. - * - * FIXME: If the incoming packet is malformed, the server drops it on - * the floor. Should it try and generate some sort of reply for the - * client? As it is, the client will simply get a broken connection. - * - * FIXME: also check write and read result for -1. - */ - -void -client_request::handle (transport_layer_base *const conn, - process_cache *const cache) -{ - if (msglen () && !_buf) - { - system_printf ("no buffer for request body: %ld bytes needed", - msglen ()); - error_code (EINVAL); - return; - } - - if (msglen () > _buflen) - { - system_printf (("buffer too small for request body: " - "have %ld bytes and need %ld"), - _buflen, msglen ()); - error_code (EINVAL); - return; - } - - if (msglen ()) - { - const ssize_t count = conn->read (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("request body read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("request received (%ld + %ld bytes)", - // sizeof (_header), msglen ()); - - error_code (0); // Overwrites the _header.request_code field. - - /* - * This is not allowed to fail. We must return ENOSYS at a minimum - * to the client. - */ - serve (conn, cache); - - { - const ssize_t count = conn->write (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("reply header write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen ()) - { - const ssize_t count = conn->write (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("reply body write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("reply sent (%ld + %ld bytes)", - // sizeof (_header), msglen ()); -} - -#endif /* !__INSIDE_CYGWIN__ */ - -bool -check_cygserver_available () -{ - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_UNAVAIL); - - cygserver_running = CYGSERVER_OK; // For make_request (). - - client_request_get_version req; - - /* This indicates that we failed to connect to cygserver at all but - * that's fine as cygwin doesn't need it to be running. - */ - if (req.make_request () == -1) - return false; - - /* We connected to the server but something went wrong after that - * (in sending the message, in cygserver itself, or in receiving the - * reply). - */ - if (req.error_code ()) - { - syscall_printf ("failure in cygserver version request: %d", - req.error_code ()); - syscall_printf ("process will continue without cygserver support"); - return false; - } - - return req.check_version (); -} - -void -cygserver_init () -{ - if (!allow_daemon) - { - syscall_printf ("cygserver use disabled in client"); - cygserver_running = CYGSERVER_UNAVAIL; - return; - } - - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - if (cygserver_running == CYGSERVER_OK) - return; - - if (!check_cygserver_available ()) - cygserver_running = CYGSERVER_UNAVAIL; -} diff --git a/winsup/cygwin/cygserver_ipc.h b/winsup/cygwin/cygserver_ipc.h deleted file mode 100644 index 0d0ebbc..0000000 --- a/winsup/cygwin/cygserver_ipc.h +++ /dev/null @@ -1,84 +0,0 @@ -/* cygserver_ipc.h - - Copyright 2002 Red Hat, Inc. - - Originally written by Conrad Scott <conrad.scott@dsl.pipex.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef __CYGSERVER_IPC_H__ -#define __CYGSERVER_IPC_H__ - -#include <assert.h> -#include <limits.h> /* For OPEN_MAX. */ - -/* - * The sysv ipc id's (msgid, semid, shmid) are integers arranged such - * that they no subsystem will generate the same id as some other - * subsystem; nor do these ids overlap file descriptors (the other - * common integer ids). Since Cygwin can allocate more than OPEN_MAX - * file descriptors, it can't be guaranteed not to overlap, but it - * should help catch some errors. - * - * msgid's: OPEN_MAX, OPEN_MAX + 3, OPEN_MAX + 6, . . . - * semid's: OPEN_MAX + 1, OPEN_MAX + 4, OPEN_MAX + 7, . . . - * shmid's: OPEN_MAX + 2, OPEN_MAX + 5, OPEN_MAX + 8, . . . - * - * To further ensure that ids are unique, if ipc objects are created - * and destroyed and then re-created, they are given new ids by - * munging the basic id (as above) with a sequence number. - * - * Internal ipc id's, which are 0, 1, ... within each subsystem (and - * not munged with a sequence number), are used solely by the ipcs(8) - * interface. - */ - -enum ipc_subsys_t - { - IPC_MSGOP = 0, - IPC_SEMOP = 1, - IPC_SHMOP = 2, - IPC_SUBSYS_COUNT - }; - -/* - * IPCMNI - The absolute maximum number of simultaneous ipc ids for - * any one subsystem. - */ - -enum - { - IPCMNI = 0x10000 // Must be a power of two. - }; - -inline int -ipc_int2ext (const int intid, const ipc_subsys_t subsys, long & sequence) -{ - assert (0 <= intid && intid < IPCMNI); - - const long tmp = InterlockedIncrement (&sequence); - - return (((tmp & 0x7fff) << 16) - | (OPEN_MAX + (intid * IPC_SUBSYS_COUNT) + subsys)); -} - -inline int -ipc_ext2int_subsys (const int extid) -{ - return ((extid & (IPCMNI - 1)) - OPEN_MAX) % IPC_SUBSYS_COUNT; -} - -inline int -ipc_ext2int (const int extid, const ipc_subsys_t subsys) -{ - if (ipc_ext2int_subsys (extid) != subsys) - return -1; - else - return ((extid & (IPCMNI - 1)) - OPEN_MAX) / IPC_SUBSYS_COUNT; -} - -#endif /* __CYGSERVER_IPC_H__ */ diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc deleted file mode 100755 index 2cc7be1..0000000 --- a/winsup/cygwin/cygserver_process.cc +++ /dev/null @@ -1,431 +0,0 @@ -/* cygserver_process.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "woutsup.h" - -#include <sys/types.h> - -#include <assert.h> -#include <stdlib.h> - -#include "cygerrno.h" - -#include "cygwin/cygserver_process.h" - -/*****************************************************************************/ - -#define elements(ARRAY) (sizeof (ARRAY) / sizeof (*ARRAY)) - -/*****************************************************************************/ - -process_cleanup::~process_cleanup () -{ - safe_delete (_process); -} - -void -process_cleanup::process () -{ - _process->cleanup (); -} - -/*****************************************************************************/ - -/* cleanup_routine */ -cleanup_routine::~cleanup_routine () -{ -} - -/*****************************************************************************/ - -process::process (const pid_t cygpid, const DWORD winpid) - : _cygpid (cygpid), - _winpid (winpid), - _hProcess (NULL), - _cleaning_up (false), - _exit_status (STILL_ACTIVE), - _routines_head (NULL), - _next (NULL) -{ - _hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid); - if (!_hProcess) - { - system_printf ("unable to obtain handle for new cache process %d(%lu)", - _cygpid, _winpid); - _hProcess = INVALID_HANDLE_VALUE; - _exit_status = 0; - } - else - debug_printf ("got handle %p for new cache process %d(%lu)", - _hProcess, _cygpid, _winpid); - InitializeCriticalSection (&_access); -} - -process::~process () -{ - DeleteCriticalSection (&_access); - (void) CloseHandle (_hProcess); -} - -/* No need to be thread-safe as this is only ever called by - * process_cache::remove_process (). If it has to be made thread-safe - * later on, it should not use the `access' critical section as that - * is held by the client request handlers for an arbitrary length of - * time, i.e. while they do whatever processing is required for a - * client request. - */ -DWORD -process::check_exit_code () -{ - if (_hProcess && _hProcess != INVALID_HANDLE_VALUE - && _exit_status == STILL_ACTIVE - && !GetExitCodeProcess (_hProcess, &_exit_status)) - { - system_printf ("failed to retrieve exit code for %d(%lu), error = %lu", - _cygpid, _winpid, GetLastError ()); - _hProcess = INVALID_HANDLE_VALUE; - } - return _exit_status; -} - -bool -process::add (cleanup_routine *const entry) -{ - assert (entry); - - bool res = false; - EnterCriticalSection (&_access); - - if (!_cleaning_up) - { - entry->_next = _routines_head; - _routines_head = entry; - res = true; - } - - LeaveCriticalSection (&_access); - return res; -} - -bool -process::remove (const cleanup_routine *const entry) -{ - assert (entry); - - bool res = false; - EnterCriticalSection (&_access); - - if (!_cleaning_up) - { - cleanup_routine *previous = NULL; - - for (cleanup_routine *ptr = _routines_head; - ptr; - previous = ptr, ptr = ptr->_next) - { - if (*ptr == *entry) - { - if (previous) - previous->_next = ptr->_next; - else - _routines_head = ptr->_next; - - safe_delete (ptr); - res = true; - break; - } - } - } - - LeaveCriticalSection (&_access); - return res; -} - -/* This is single threaded. It's called after the process is removed - * from the cache, but inserts may be attemped by worker threads that - * have a pointer to it. - */ -void -process::cleanup () -{ - EnterCriticalSection (&_access); - assert (!is_active ()); - assert (!_cleaning_up); - InterlockedExchange (&_cleaning_up, true); - cleanup_routine *entry = _routines_head; - _routines_head = NULL; - LeaveCriticalSection (&_access); - - while (entry) - { - cleanup_routine *const ptr = entry; - entry = entry->_next; - ptr->cleanup (this); - safe_delete (ptr); - } -} - -/*****************************************************************************/ - -void -process_cache::submission_loop::request_loop () -{ - assert (this); - assert (_cache); - assert (_interrupt_event); - - while (_running) - _cache->wait_for_processes (_interrupt_event); -} - -/*****************************************************************************/ - -process_cache::process_cache (const unsigned int initial_workers) - : _queue (initial_workers), - _submitter (this, &_queue), // true == interruptible - _processes_count (0), - _processes_head (NULL), - _cache_add_trigger (NULL) -{ - /* there can only be one */ - InitializeCriticalSection (&_cache_write_access); - - _cache_add_trigger = CreateEvent (NULL, // SECURITY_ATTRIBUTES - FALSE, // Auto-reset - FALSE, // Initially non-signalled - NULL); // Anonymous - - if (!_cache_add_trigger) - { - system_printf ("failed to create cache add trigger, error = %lu", - GetLastError ()); - abort (); - } - - _queue.add_submission_loop (&_submitter); -} - -process_cache::~process_cache () -{ - (void) CloseHandle (_cache_add_trigger); - DeleteCriticalSection (&_cache_write_access); -} - -/* This returns the process object to the caller already locked, that - * is, with the object's `access' critical region entered. Thus the - * caller must unlock the object when it's finished with it (via - * process::release ()). It must then not try to access the object - * afterwards, except by going through this routine again, as it may - * have been deleted once it has been unlocked. - */ -class process * -process_cache::process (const pid_t cygpid, const DWORD winpid) -{ - /* TODO: make this more granular, so a search doesn't involve the - * write lock. - */ - EnterCriticalSection (&_cache_write_access); - class process *previous = NULL; - class process *entry = find (winpid, &previous); - - if (!entry) - { - if (_processes_count + SPECIALS_COUNT >= MAXIMUM_WAIT_OBJECTS) - { - LeaveCriticalSection (&_cache_write_access); - system_printf (("process limit (%d processes) reached; " - "new connection refused for %d(%lu)"), - MAXIMUM_WAIT_OBJECTS - SPECIALS_COUNT, - cygpid, winpid); - set_errno (EAGAIN); - return NULL; - } - - entry = safe_new (class process, cygpid, winpid); - if (!entry->is_active ()) - { - LeaveCriticalSection (&_cache_write_access); - safe_delete (entry); - set_errno (ESRCH); - return NULL; - } - - if (previous) - { - entry->_next = previous->_next; - previous->_next = entry; - } - else - { - entry->_next = _processes_head; - _processes_head = entry; - } - - _processes_count += 1; - SetEvent (_cache_add_trigger); - } - - EnterCriticalSection (&entry->_access); // To be released by the caller. - LeaveCriticalSection (&_cache_write_access); - assert (entry); - assert (entry->_winpid == winpid); - return entry; -} - -void -process_cache::wait_for_processes (const HANDLE interrupt_event) -{ - // Update `_wait_array' with handles of all current processes. - const size_t count = sync_wait_array (interrupt_event); - - debug_printf ("waiting on %u objects in total (%u processes)", - count, _processes_count); - - const DWORD rc = WaitForMultipleObjects (count, _wait_array, - FALSE, INFINITE); - - if (rc == WAIT_FAILED) - { - system_printf ("could not wait on the process handles, error = %lu", - GetLastError ()); - abort (); - } - - const size_t start = rc - WAIT_OBJECT_0; - - if (rc < WAIT_OBJECT_0 || start > count) - { - system_printf (("unexpected return code %rc " - "from WaitForMultipleObjects: " - "expected [%u .. %u)"), - rc, WAIT_OBJECT_0, WAIT_OBJECT_0 + count); - abort (); - } - - // Tell all the processes, from the signalled point up, the bad news. - for (size_t index = start; index != count; index++) - if (_process_array[index]) - check_and_remove_process (index); -} - -/* - * process_cache::sync_wait_array () - * - * Fill-in the wait array with the handles that the cache needs to wait on. - * These handles are: - * - the process_process_param's interrupt event - * - the process_cache's cache_add_trigger event - * - the handle for each live process in the cache. - * - * Return value: the number of live handles in the array. - */ - -size_t -process_cache::sync_wait_array (const HANDLE interrupt_event) -{ - assert (this); - assert (_cache_add_trigger && _cache_add_trigger != INVALID_HANDLE_VALUE); - assert (interrupt_event && interrupt_event != INVALID_HANDLE_VALUE); - - EnterCriticalSection (&_cache_write_access); - - assert (_processes_count + SPECIALS_COUNT <= elements (_wait_array)); - - size_t index = 0; - - for (class process *ptr = _processes_head; ptr; ptr = ptr->_next) - { - assert (ptr->_hProcess && ptr->_hProcess != INVALID_HANDLE_VALUE); - assert (ptr->is_active ()); - - _wait_array[index] = ptr->handle (); - _process_array[index++] = ptr; - - assert (index <= elements (_wait_array)); - } - - /* Sorry for shouting, but THESE MUST BE ADDED AT THE END! */ - /* Well, not strictly `must', but it's more efficient if they are :-) */ - - _wait_array[index] = interrupt_event; - _process_array[index++] = NULL; - - _wait_array[index] = _cache_add_trigger; - _process_array[index++] = NULL; - - /* Phew, back to normal volume now. */ - - assert (index <= elements (_wait_array)); - - LeaveCriticalSection (&_cache_write_access); - - return index; -} - -void -process_cache::check_and_remove_process (const size_t index) -{ - assert (this); - assert (index < elements (_wait_array) - SPECIALS_COUNT); - - class process *const process = _process_array[index]; - - assert (process); - assert (process->handle () == _wait_array[index]); - - if (process->check_exit_code () == STILL_ACTIVE) - return; - - debug_printf ("process %d(%lu) has left the building ($? = %lu)", - process->_cygpid, process->_winpid, process->_exit_status); - - /* Unlink the process object from the process list. */ - - EnterCriticalSection (&_cache_write_access); - - class process *previous = NULL; - - const class process *const tmp = find (process->_winpid, &previous); - - assert (tmp == process); - assert (previous ? previous->_next == process : _processes_head == process); - - if (previous) - previous->_next = process->_next; - else - _processes_head = process->_next; - - _processes_count -= 1; - LeaveCriticalSection (&_cache_write_access); - - /* Schedule any cleanup tasks for this process. */ - _queue.add (safe_new (process_cleanup, process)); -} - -class process * -process_cache::find (const DWORD winpid, class process **previous) -{ - if (previous) - *previous = NULL; - - for (class process *ptr = _processes_head; ptr; ptr = ptr->_next) - if (ptr->_winpid == winpid) - return ptr; - else if (ptr->_winpid > winpid) // The list is sorted by winpid. - return NULL; - else if (previous) - *previous = ptr; - - return NULL; -} - -/*****************************************************************************/ diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc deleted file mode 100755 index 90053ee..0000000 --- a/winsup/cygwin/cygserver_shm.cc +++ /dev/null @@ -1,896 +0,0 @@ -/* cygserver_shm.cc: Single unix specification IPC interface for Cygwin. - - Copyright 2002 Red Hat, Inc. - - Written by Conrad Scott <conrad.scott@dsl.pipex.com>. - Based on code by Robert Collins <robert.collins@hotmail.com>. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "woutsup.h" - -#include <errno.h> -#include <pthread.h> -#include <stdio.h> -#include <string.h> -#include <time.h> - -#include "cygserver_ipc.h" -#include "cygserver_shm.h" -#include "security.h" - -#include "cygwin/cygserver.h" -#include "cygwin/cygserver_process.h" -#include "cygwin/cygserver_transport.h" - -/*---------------------------------------------------------------------------* - * class server_shmmgr - * - * A singleton class. - *---------------------------------------------------------------------------*/ - -#define shmmgr (server_shmmgr::instance ()) - -class server_shmmgr -{ -private: - class attach_t - { - public: - class process *const _client; - unsigned int _refcnt; - - attach_t *_next; - - attach_t (class process *const client) - : _client (client), - _refcnt (0), - _next (NULL) - {} - }; - - class segment_t - { - private: - // Bits for the _flg field. - enum { IS_DELETED = 0x01 }; - - public: - const int _intid; - const int _shmid; - struct shmid_ds _ds; - - segment_t *_next; - - segment_t (const key_t key, const int intid, const HANDLE hFileMap); - ~segment_t (); - - bool is_deleted () const - { - return _flg & IS_DELETED; - } - - bool is_pending_delete () const - { - return !_ds.shm_nattch && is_deleted (); - } - - void mark_deleted () - { - assert (!is_deleted ()); - - _flg |= IS_DELETED; - } - - int attach (class process *, HANDLE & hFileMap); - int detach (class process *); - - private: - static long _sequence; - - int _flg; - const HANDLE _hFileMap; - attach_t *_attach_head; // A list sorted by winpid; - - attach_t *find (const class process *, attach_t **previous = NULL); - }; - - class cleanup_t : public cleanup_routine - { - public: - cleanup_t (const segment_t *const segptr) - : cleanup_routine (reinterpret_cast<void *> (segptr->_shmid)) - { - assert (key ()); - } - - int shmid () const { return reinterpret_cast<int> (key ()); } - - virtual void cleanup (class process *const client) - { - const int res = shmmgr.shmdt (shmid (), client); - - if (res != 0) - debug_printf ("process cleanup failed [shmid = %d]: %s", - shmid (), strerror (-res)); - } - }; - -public: - static server_shmmgr & instance (); - - int shmat (HANDLE & hFileMap, - int shmid, int shmflg, class process *); - int shmctl (int & out_shmid, struct shmid_ds & out_ds, - struct shminfo & out_shminfo, struct shm_info & out_shm_info, - const int shmid, int cmd, const struct shmid_ds &, - class process *); - int shmdt (int shmid, class process *); - int shmget (int & out_shmid, key_t, size_t, int shmflg, uid_t, gid_t, - class process *); - -private: - static server_shmmgr *_instance; - static pthread_once_t _instance_once; - - static void initialise_instance (); - - CRITICAL_SECTION _segments_lock; - segment_t *_segments_head; // A list sorted by int_id. - - int _shm_ids; // Number of shm segments (for ipcs(8)). - int _shm_tot; // Total bytes of shm segments (for ipcs(8)). - int _shm_atts; // Number of attached segments (for ipcs(8)). - int _intid_max; // Highest intid yet allocated (for ipcs(8)). - - server_shmmgr (); - ~server_shmmgr (); - - // Undefined (as this class is a singleton): - server_shmmgr (const server_shmmgr &); - server_shmmgr & operator= (const server_shmmgr &); - - segment_t *find_by_key (key_t); - segment_t *find (int intid, segment_t **previous = NULL); - - int new_segment (key_t, size_t, int shmflg, pid_t, uid_t, gid_t); - - segment_t *new_segment (key_t, size_t, HANDLE); - void delete_segment (segment_t *); -}; - -/* static */ long server_shmmgr::segment_t::_sequence = 0; - -/* static */ server_shmmgr *server_shmmgr::_instance = NULL; -/* static */ pthread_once_t server_shmmgr::_instance_once = PTHREAD_ONCE_INIT; - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::segment_t () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t::segment_t (const key_t key, - const int intid, - const HANDLE hFileMap) - : _intid (intid), - _shmid (ipc_int2ext (intid, IPC_SHMOP, _sequence)), - _next (NULL), - _flg (0), - _hFileMap (hFileMap), - _attach_head (NULL) -{ - assert (0 <= _intid && _intid < SHMMNI); - - memset (&_ds, '\0', sizeof (_ds)); - _ds.shm_perm.key = key; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::~segment_t () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t::~segment_t () -{ - assert (!_attach_head); - - if (!CloseHandle (_hFileMap)) - syscall_printf ("failed to close file map [handle = 0x%x]: %E", _hFileMap); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::attach () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::segment_t::attach (class process *const client, - HANDLE & hFileMap) -{ - assert (client); - - if (!DuplicateHandle (GetCurrentProcess (), - _hFileMap, - client->handle (), - &hFileMap, - 0, - FALSE, // bInheritHandle - DUPLICATE_SAME_ACCESS)) - { - syscall_printf (("failed to duplicate handle for client " - "[key = 0x%016llx, shmid = %d, handle = 0x%x]: %E"), - _ds.shm_perm.key, _shmid, _hFileMap); - - return -EACCES; // FIXME: Case analysis? - } - - _ds.shm_lpid = client->cygpid (); - _ds.shm_nattch += 1; - _ds.shm_atime = time (NULL); // FIXME: sub-second times. - - attach_t *previous = NULL; - attach_t *attptr = find (client, &previous); - - if (!attptr) - { - attptr = safe_new (attach_t, client); - - if (previous) - { - attptr->_next = previous->_next; - previous->_next = attptr; - } - else - { - attptr->_next = _attach_head; - _attach_head = attptr; - } - } - - attptr->_refcnt += 1; - - cleanup_t *const cleanup = safe_new (cleanup_t, this); - - // FIXME: ::add should only fail if the process object is already - // cleaning up; but it can't be doing that since this thread has it - // locked. - - const bool result = client->add (cleanup); - - assert (result); - - return 0; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::detach () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::segment_t::detach (class process *const client) -{ - attach_t *previous = NULL; - attach_t *const attptr = find (client, &previous); - - if (!attptr) - return -EINVAL; - - if (client->is_active ()) - { - const cleanup_t key (this); - - if (!client->remove (&key)) - syscall_printf (("failed to remove cleanup routine for %d(%lu) " - "[shmid = %d]"), - client->cygpid (), client->winpid (), - _shmid); - } - - attptr->_refcnt -= 1; - - if (!attptr->_refcnt) - { - assert (previous ? previous->_next == attptr : _attach_head == attptr); - - if (previous) - previous->_next = attptr->_next; - else - _attach_head = attptr->_next; - - safe_delete (attptr); - } - - assert (_ds.shm_nattch > 0); - - _ds.shm_lpid = client->cygpid (); - _ds.shm_nattch -= 1; - _ds.shm_dtime = time (NULL); // FIXME: sub-second times. - - return 0; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::find () - *---------------------------------------------------------------------------*/ - -server_shmmgr::attach_t * -server_shmmgr::segment_t::find (const class process *const client, - attach_t **previous) -{ - if (previous) - *previous = NULL; - - // Nb. The _attach_head list is sorted by winpid. - - for (attach_t *attptr = _attach_head; attptr; attptr = attptr->_next) - if (attptr->_client == client) - return attptr; - else if (attptr->_client->winpid () > client->winpid ()) - return NULL; - else if (previous) - *previous = attptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::instance () - *---------------------------------------------------------------------------*/ - -/* static */ server_shmmgr & -server_shmmgr::instance () -{ - pthread_once (&_instance_once, &initialise_instance); - - assert (_instance); - - return *_instance; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmat () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmat (HANDLE & hFileMap, - const int shmid, const int shmflg, - class process *const client) -{ - syscall_printf ("shmat (shmid = %d, shmflg = 0%o) for %d(%lu)", - shmid, shmflg, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP)); - - if (!segptr) - result = -EINVAL; - else - result = segptr->attach (client, hFileMap); - - if (!result) - _shm_atts += 1; - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf (("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) " - "for %d(%lu)"), - -result, shmid, shmflg, - client->cygpid (), client->winpid ()); - else - syscall_printf (("0x%x = shmat (shmid = %d, shmflg = 0%o) " - "for %d(%lu)"), - hFileMap, shmid, shmflg, - client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmctl () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmctl (int & out_shmid, - struct shmid_ds & out_ds, - struct shminfo & out_shminfo, - struct shm_info & out_shm_info, - const int shmid, const int cmd, - const struct shmid_ds & ds, - class process *const client) -{ - syscall_printf ("shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)", - shmid, cmd, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - switch (cmd) - { - case IPC_STAT: - case SHM_STAT: // Uses intids rather than shmids. - case IPC_SET: - case IPC_RMID: - { - int intid; - - if (cmd == SHM_STAT) - intid = shmid; - else - intid = ipc_ext2int (shmid, IPC_SHMOP); - - segment_t *const segptr = find (intid); - - if (!segptr) - result = -EINVAL; - else - switch (cmd) - { - case IPC_STAT: - out_ds = segptr->_ds; - break; - - case IPC_SET: - segptr->_ds.shm_perm.uid = ds.shm_perm.uid; - segptr->_ds.shm_perm.gid = ds.shm_perm.gid; - segptr->_ds.shm_perm.mode = ds.shm_perm.mode & 0777; - segptr->_ds.shm_lpid = client->cygpid (); - segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times. - break; - - case IPC_RMID: - if (segptr->is_deleted ()) - result = -EIDRM; - else - { - segptr->mark_deleted (); - if (segptr->is_pending_delete ()) - delete_segment (segptr); - } - break; - - case SHM_STAT: // ipcs(8) i'face. - out_ds = segptr->_ds; - out_shmid = segptr->_shmid; - break; - } - } - break; - - case IPC_INFO: - out_shminfo.shmmax = SHMMAX; - out_shminfo.shmmin = SHMMIN; - out_shminfo.shmmni = SHMMNI; - out_shminfo.shmseg = SHMSEG; - out_shminfo.shmall = SHMALL; - break; - - case SHM_INFO: // ipcs(8) i'face. - out_shmid = _intid_max; - out_shm_info.shm_ids = _shm_ids; - out_shm_info.shm_tot = _shm_tot; - out_shm_info.shm_atts = _shm_atts; - break; - - default: - result = -EINVAL; - break; - } - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf (("-1 [%d] = " - "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"), - -result, - shmid, cmd, client->cygpid (), client->winpid ()); - else - syscall_printf (("%d = " - "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"), - ((cmd == SHM_STAT || cmd == SHM_INFO) - ? out_shmid - : result), - shmid, cmd, client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmdt () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmdt (const int shmid, class process *const client) -{ - syscall_printf ("shmdt (shmid = %d) for %d(%lu)", - shmid, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP)); - - if (!segptr) - result = -EINVAL; - else - result = segptr->detach (client); - - if (!result) - _shm_atts -= 1; - - if (!result && segptr->is_pending_delete ()) - delete_segment (segptr); - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf ("-1 [%d] = shmdt (shmid = %d) for %d(%lu)", - -result, shmid, client->cygpid (), client->winpid ()); - else - syscall_printf ("%d = shmdt (shmid = %d) for %d(%lu)", - result, shmid, client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmget () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmget (int & out_shmid, - const key_t key, const size_t size, const int shmflg, - const uid_t uid, const gid_t gid, - class process *const client) -{ - syscall_printf (("shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - key, size, shmflg, - client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - if (key == IPC_PRIVATE) - result = new_segment (key, size, shmflg, - client->cygpid (), uid, gid); - else - { - segment_t *const segptr = find_by_key (key); - - if (!segptr) - if (shmflg & IPC_CREAT) - result = new_segment (key, size, shmflg, - client->cygpid (), uid, gid); - else - result = -ENOENT; - else if (segptr->is_deleted ()) - result = -EIDRM; - else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) - result = -EEXIST; - else if ((shmflg & ~(segptr->_ds.shm_perm.mode)) & 0777) - result = -EACCES; - else if (size && segptr->_ds.shm_segsz < size) - result = -EINVAL; - else - result = segptr->_shmid; - } - - LeaveCriticalSection (&_segments_lock); - - if (result >= 0) - { - out_shmid = result; - result = 0; - } - - if (result < 0) - syscall_printf (("-1 [%d] = " - "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - -result, - key, size, shmflg, - client->cygpid (), client->winpid ()); - else - syscall_printf (("%d = " - "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - out_shmid, - key, size, shmflg, - client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::initialise_instance () - *---------------------------------------------------------------------------*/ - -/* static */ void -server_shmmgr::initialise_instance () -{ - assert (!_instance); - - _instance = safe_new0 (server_shmmgr); - - assert (_instance); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::server_shmmgr () - *---------------------------------------------------------------------------*/ - -server_shmmgr::server_shmmgr () - : _segments_head (NULL), - _shm_ids (0), - _shm_tot (0), - _shm_atts (0), - _intid_max (0) -{ - InitializeCriticalSection (&_segments_lock); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::~server_shmmgr () - *---------------------------------------------------------------------------*/ - -server_shmmgr::~server_shmmgr () -{ - DeleteCriticalSection (&_segments_lock); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::find_by_key () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::find_by_key (const key_t key) -{ - for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next) - if (segptr->_ds.shm_perm.key == key) - return segptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::find () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::find (const int intid, segment_t **previous) -{ - if (previous) - *previous = NULL; - - for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next) - if (segptr->_intid == intid) - return segptr; - else if (segptr->_intid > intid) // The list is sorted by intid. - return NULL; - else if (previous) - *previous = segptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::new_segment () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::new_segment (const key_t key, - const size_t size, - const int shmflg, - const pid_t cygpid, - const uid_t uid, - const gid_t gid) -{ - if (size < SHMMIN || size > SHMMAX) - return -EINVAL; - - const HANDLE hFileMap = CreateFileMapping (INVALID_HANDLE_VALUE, - NULL, PAGE_READWRITE, - 0, size, - NULL); - - if (!hFileMap) - { - syscall_printf ("failed to create file mapping [size = %lu]: %E", size); - return -ENOMEM; // FIXME - } - - segment_t *const segptr = new_segment (key, size, hFileMap); - - if (!segptr) - { - (void) CloseHandle (hFileMap); - return -ENOSPC; - } - - segptr->_ds.shm_perm.cuid = segptr->_ds.shm_perm.uid = uid; - segptr->_ds.shm_perm.cgid = segptr->_ds.shm_perm.gid = gid; - segptr->_ds.shm_perm.mode = shmflg & 0777; - segptr->_ds.shm_segsz = size; - segptr->_ds.shm_cpid = cygpid; - segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times. - - return segptr->_shmid; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::new_segment () - * - * Allocate a new segment for the given key and file map with the - * lowest available intid and insert into the segment map. - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::new_segment (const key_t key, const size_t size, - const HANDLE hFileMap) -{ - // FIXME: Overflow risk. - if (_shm_tot + size > SHMALL) - return NULL; - - int intid = 0; // Next expected intid value. - segment_t *previous = NULL; // Insert pointer. - - // Find first unallocated intid. - for (segment_t *segptr = _segments_head; - segptr && segptr->_intid == intid; - segptr = segptr->_next, intid++) - { - previous = segptr; - } - - /* By the time this condition is reached (given the default value of - * SHMMNI), the linear searches should all replaced by something - * just a *little* cleverer . . . - */ - if (intid >= SHMMNI) - return NULL; - - segment_t *const segptr = safe_new (segment_t, key, intid, hFileMap); - - assert (segptr); - - if (previous) - { - segptr->_next = previous->_next; - previous->_next = segptr; - } - else - { - segptr->_next = _segments_head; - _segments_head = segptr; - } - - _shm_ids += 1; - _shm_tot += size; - if (intid > _intid_max) - _intid_max = intid; - - return segptr; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::delete_segment () - *---------------------------------------------------------------------------*/ - -void -server_shmmgr::delete_segment (segment_t *const segptr) -{ - assert (segptr); - assert (segptr->is_pending_delete ()); - - segment_t *previous = NULL; - - const segment_t *const tmp = find (segptr->_intid, &previous); - - assert (tmp == segptr); - assert (previous ? previous->_next == segptr : _segments_head == segptr); - - if (previous) - previous->_next = segptr->_next; - else - _segments_head = segptr->_next; - - assert (_shm_ids > 0); - _shm_ids -= 1; - _shm_tot -= segptr->_ds.shm_segsz; - - safe_delete (segptr); -} - -/*---------------------------------------------------------------------------* - * client_request_shm::client_request_shm () - *---------------------------------------------------------------------------*/ - -client_request_shm::client_request_shm () - : client_request (CYGSERVER_REQUEST_SHM, - &_parameters, sizeof (_parameters)) -{ - // verbose: syscall_printf ("created"); -} - -/*---------------------------------------------------------------------------* - * client_request_shm::serve () - *---------------------------------------------------------------------------*/ - -void -client_request_shm::serve (transport_layer_base *const conn, - process_cache *const cache) -{ - assert (conn); - - assert (!error_code ()); - - if (msglen () != sizeof (_parameters.in)) - { - syscall_printf ("bad request body length: expecting %lu bytes, got %lu", - sizeof (_parameters), msglen ()); - error_code (EINVAL); - msglen (0); - return; - } - - // FIXME: Get a return code out of this and don't continue on error. - conn->impersonate_client (); - - class process *const client = cache->process (_parameters.in.cygpid, - _parameters.in.winpid); - - if (!client) - { - error_code (EAGAIN); - msglen (0); - return; - } - - int result = -EINVAL; - - switch (_parameters.in.shmop) - { - case SHMOP_shmget: - result = shmmgr.shmget (_parameters.out.shmid, - _parameters.in.key, _parameters.in.size, - _parameters.in.shmflg, - _parameters.in.uid, _parameters.in.gid, - client); - break; - - case SHMOP_shmat: - result = shmmgr.shmat (_parameters.out.hFileMap, - _parameters.in.shmid, _parameters.in.shmflg, - client); - break; - - case SHMOP_shmdt: - result = shmmgr.shmdt (_parameters.in.shmid, client); - break; - - case SHMOP_shmctl: - result = shmmgr.shmctl (_parameters.out.shmid, - _parameters.out.ds, _parameters.out.shminfo, - _parameters.out.shm_info, - _parameters.in.shmid, _parameters.in.cmd, - _parameters.in.ds, - client); - break; - } - - client->release (); - conn->revert_to_self (); - - if (result < 0) - { - error_code (-result); - msglen (0); - } - else - msglen (sizeof (_parameters.out)); -} diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h deleted file mode 100644 index 5a5ee38..0000000 --- a/winsup/cygwin/cygserver_shm.h +++ /dev/null @@ -1,147 +0,0 @@ -/* cygserver_shm.h: Single unix specification IPC interface for Cygwin. - - Copyright 2002 Red Hat, Inc. - - Written by Conrad Scott <conrad.scott@dsl.pipex.com>. - Based on code by Robert Collins <robert.collins@hotmail.com>. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef __CYGSERVER_SHM_H__ -#define __CYGSERVER_SHM_H__ - -#include <sys/types.h> -#include <cygwin/shm.h> - -#include <assert.h> -#include <limits.h> - -#include "cygserver_ipc.h" - -#include "cygwin/cygserver.h" - -/*---------------------------------------------------------------------------* - * Values for the shminfo entries. - * - * Nb. The values are segregated between two enums so that the `small' - * values aren't promoted to `unsigned long' equivalents. - *---------------------------------------------------------------------------*/ - -enum - { - SHMMAX = ULONG_MAX, - SHMSEG = ULONG_MAX, - SHMALL = ULONG_MAX - }; - -enum - { - SHMMIN = 1, - SHMMNI = IPCMNI // Must be <= IPCMNI. - }; - -/*---------------------------------------------------------------------------* - * class client_request_shm - *---------------------------------------------------------------------------*/ - -#ifndef __INSIDE_CYGWIN__ -class transport_layer_base; -class process_cache; -#endif - -class client_request_shm : public client_request -{ - friend class client_request; - -public: - enum shmop_t - { - SHMOP_shmat, - SHMOP_shmctl, - SHMOP_shmdt, - SHMOP_shmget - }; - -#ifdef __INSIDE_CYGWIN__ - client_request_shm (int shmid, int shmflg); // shmat - client_request_shm (int shmid, int cmd, const struct shmid_ds *); // shmctl - client_request_shm (int shmid); // shmdt - client_request_shm (key_t, size_t, int shmflg); // shmget -#endif - - // Accessors for out parameters. - - int shmid () const - { - assert (!error_code ()); - return _parameters.out.shmid; - } - - HANDLE hFileMap () const - { - assert (!error_code ()); - return _parameters.out.hFileMap; - } - - const struct shmid_ds & ds () const - { - assert (!error_code ()); - return _parameters.out.ds; - } - - const struct shminfo & shminfo () const - { - assert (!error_code ()); - return _parameters.out.shminfo; - } - - const struct shm_info & shm_info () const - { - assert (!error_code ()); - return _parameters.out.shm_info; - } - -private: - union - { - struct - { - shmop_t shmop; - key_t key; - size_t size; - int shmflg; - int shmid; - int cmd; - pid_t cygpid; - DWORD winpid; - __uid32_t uid; - __gid32_t gid; - struct shmid_ds ds; - } in; - - struct { - int shmid; - union - { - HANDLE hFileMap; - struct shmid_ds ds; - struct shminfo shminfo; - struct shm_info shm_info; - }; - } out; - } _parameters; - -#ifndef __INSIDE_CYGWIN__ - client_request_shm (); -#endif - -#ifndef __INSIDE_CYGWIN__ - virtual void serve (transport_layer_base *, process_cache *); -#endif -}; - -#endif /* __CYGSERVER_SHM_H__ */ diff --git a/winsup/cygwin/cygserver_transport.cc b/winsup/cygwin/cygserver_transport.cc deleted file mode 100755 index 8684a61..0000000 --- a/winsup/cygwin/cygserver_transport.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* cygserver_transport.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifdef __OUTSIDE_CYGWIN__ -#include "woutsup.h" -#else -#include "winsup.h" -#endif - -#include <sys/socket.h> - -#include "safe_memory.h" - -#include "cygwin/cygserver_transport.h" -#include "cygwin/cygserver_transport_pipes.h" -#include "cygwin/cygserver_transport_sockets.h" - -/* The factory */ -transport_layer_base * -create_server_transport () -{ - if (wincap.is_winnt ()) - return safe_new0 (transport_layer_pipes); - else - return safe_new0 (transport_layer_sockets); -} - -#ifndef __INSIDE_CYGWIN__ - -void -transport_layer_base::impersonate_client () -{} - -void -transport_layer_base::revert_to_self () -{} - -#endif /* !__INSIDE_CYGWIN__ */ - -transport_layer_base::~transport_layer_base () -{} diff --git a/winsup/cygwin/cygserver_transport_pipes.cc b/winsup/cygwin/cygserver_transport_pipes.cc deleted file mode 100755 index 6d80def..0000000 --- a/winsup/cygwin/cygserver_transport_pipes.cc +++ /dev/null @@ -1,362 +0,0 @@ -/* cygserver_transport_pipes.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifdef __OUTSIDE_CYGWIN__ -#include "woutsup.h" -#else -#include "winsup.h" -#endif - -#include <sys/types.h> - -#include <assert.h> -#include <netdb.h> -#include <pthread.h> -#include <unistd.h> - -#include "cygerrno.h" -#include "cygwin/cygserver_transport.h" -#include "cygwin/cygserver_transport_pipes.h" - -#ifndef __INSIDE_CYGWIN__ -#include "cygwin/cygserver.h" -#endif - -enum - { - MAX_WAIT_NAMED_PIPE_RETRY = 64, - WAIT_NAMED_PIPE_TIMEOUT = 10 // milliseconds - }; - -#ifndef __INSIDE_CYGWIN__ - -static pthread_once_t pipe_instance_lock_once = PTHREAD_ONCE_INIT; -static CRITICAL_SECTION pipe_instance_lock; -static long pipe_instance = 0; - -static void -initialise_pipe_instance_lock () -{ - assert (pipe_instance == 0); - InitializeCriticalSection (&pipe_instance_lock); -} - -#endif /* !__INSIDE_CYGWIN__ */ - -#ifndef __INSIDE_CYGWIN__ - -transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe) - : _pipe_name (""), - _hPipe (hPipe), - _is_accepted_endpoint (true), - _is_listening_endpoint (false) -{ - assert (_hPipe); - assert (_hPipe != INVALID_HANDLE_VALUE); - - init_security (); -} - -#endif /* !__INSIDE_CYGWIN__ */ - -transport_layer_pipes::transport_layer_pipes () - : _pipe_name ("\\\\.\\pipe\\cygwin_lpc"), - _hPipe (NULL), - _is_accepted_endpoint (false), - _is_listening_endpoint (false) -{ - init_security (); -} - -void -transport_layer_pipes::init_security () -{ - assert (wincap.has_security ()); - - /* FIXME: pthread_once or equivalent needed */ - - InitializeSecurityDescriptor (&_sd, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl (&_sd, TRUE, NULL, FALSE); - - _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES); - _sec_all_nih.lpSecurityDescriptor = &_sd; - _sec_all_nih.bInheritHandle = FALSE; -} - -transport_layer_pipes::~transport_layer_pipes () -{ - close (); -} - -#ifndef __INSIDE_CYGWIN__ - -int -transport_layer_pipes::listen () -{ - assert (!_hPipe); - assert (!_is_accepted_endpoint); - assert (!_is_listening_endpoint); - - _is_listening_endpoint = true; - - /* no-op */ - return 0; -} - -class transport_layer_pipes * -transport_layer_pipes::accept (bool *const recoverable) -{ - assert (!_hPipe); - assert (!_is_accepted_endpoint); - assert (_is_listening_endpoint); - - pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock); - - EnterCriticalSection (&pipe_instance_lock); - - // Read: http://www.securityinternals.com/research/papers/namedpipe.php - // See also the Microsoft security bulletins MS00-053 and MS01-031. - - // FIXME: Remove FILE_CREATE_PIPE_INSTANCE. - - const bool first_instance = (pipe_instance == 0); - - const HANDLE accept_pipe = - CreateNamedPipe (_pipe_name, - (PIPE_ACCESS_DUPLEX - | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0)), - (PIPE_TYPE_BYTE | PIPE_WAIT), - PIPE_UNLIMITED_INSTANCES, - 0, 0, 1000, - &_sec_all_nih); - - const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE - && pipe_instance == 0 - && GetLastError () == ERROR_ACCESS_DENIED); - - if (accept_pipe != INVALID_HANDLE_VALUE) - InterlockedIncrement (&pipe_instance); - - LeaveCriticalSection (&pipe_instance_lock); - - if (duplicate) - { - *recoverable = false; - system_printf ("failed to create named pipe: " - "is the daemon already running?"); - return NULL; - } - - if (accept_pipe == INVALID_HANDLE_VALUE) - { - debug_printf ("error creating pipe (%lu).", GetLastError ()); - *recoverable = true; // FIXME: case analysis? - return NULL; - } - - assert (accept_pipe); - - if (!ConnectNamedPipe (accept_pipe, NULL) - && GetLastError () != ERROR_PIPE_CONNECTED) - { - debug_printf ("error connecting to pipe (%lu)", GetLastError ()); - (void) CloseHandle (accept_pipe); - *recoverable = true; // FIXME: case analysis? - return NULL; - } - - return safe_new (transport_layer_pipes, accept_pipe); -} - -#endif /* !__INSIDE_CYGWIN__ */ - -void -transport_layer_pipes::close () -{ - // verbose: debug_printf ("closing pipe %p", _hPipe); - - if (_hPipe) - { - assert (_hPipe != INVALID_HANDLE_VALUE); - -#ifndef __INSIDE_CYGWIN__ - - if (_is_accepted_endpoint) - { - (void) FlushFileBuffers (_hPipe); // Blocks until client reads. - (void) DisconnectNamedPipe (_hPipe); - EnterCriticalSection (&pipe_instance_lock); - (void) CloseHandle (_hPipe); - assert (pipe_instance > 0); - InterlockedDecrement (&pipe_instance); - LeaveCriticalSection (&pipe_instance_lock); - } - else - (void) CloseHandle (_hPipe); - -#else /* __INSIDE_CYGWIN__ */ - - assert (!_is_accepted_endpoint); - (void) ForceCloseHandle (_hPipe); - -#endif /* __INSIDE_CYGWIN__ */ - - _hPipe = NULL; - } -} - -ssize_t -transport_layer_pipes::read (void *const buf, const size_t len) -{ - // verbose: debug_printf ("reading from pipe %p", _hPipe); - - assert (_hPipe); - assert (_hPipe != INVALID_HANDLE_VALUE); - assert (!_is_listening_endpoint); - - DWORD count; - if (!ReadFile (_hPipe, buf, len, &count, NULL)) - { - debug_printf ("error reading from pipe (%lu)", GetLastError ()); - set_errno (EINVAL); // FIXME? - return -1; - } - - return count; -} - -ssize_t -transport_layer_pipes::write (void *const buf, const size_t len) -{ - // verbose: debug_printf ("writing to pipe %p", _hPipe); - - assert (_hPipe); - assert (_hPipe != INVALID_HANDLE_VALUE); - assert (!_is_listening_endpoint); - - DWORD count; - if (!WriteFile (_hPipe, buf, len, &count, NULL)) - { - debug_printf ("error writing to pipe, error = %lu", GetLastError ()); - set_errno (EINVAL); // FIXME? - return -1; - } - - return count; -} - -/* - * This routine holds a static variable, assume_cygserver, that is set - * if the transport has good reason to think that cygserver is - * running, i.e. if if successfully connected to it with the previous - * attempt. If this is set, the code tries a lot harder to get a - * connection, making the assumption that any failures are just - * congestion and overloading problems. - */ - -int -transport_layer_pipes::connect () -{ - assert (!_hPipe); - assert (!_is_accepted_endpoint); - assert (!_is_listening_endpoint); - - static bool assume_cygserver = false; - - BOOL rc = TRUE; - int retries = 0; - - while (rc) - { - _hPipe = CreateFile (_pipe_name, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &_sec_all_nih, - OPEN_EXISTING, - SECURITY_IMPERSONATION, - NULL); - - if (_hPipe != INVALID_HANDLE_VALUE) - { - assert (_hPipe); -#ifdef __INSIDE_CYGWIN__ - ProtectHandle (_hPipe); -#endif - assume_cygserver = true; - return 0; - } - - _hPipe = NULL; - - if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY) - { - debug_printf ("Error opening the pipe (%lu)", GetLastError ()); - return -1; - } - - /* Note: `If no instances of the specified named pipe exist, the - * WaitNamedPipe function returns immediately, regardless of the - * time-out value.' Thus the explicit Sleep if the call fails - * with ERROR_FILE_NOT_FOUND. - */ - while (retries != MAX_WAIT_NAMED_PIPE_RETRY - && !(rc = WaitNamedPipe (_pipe_name, WAIT_NAMED_PIPE_TIMEOUT))) - { - if (GetLastError () == ERROR_FILE_NOT_FOUND) - Sleep (0); // Give the server a chance. - - retries += 1; - } - } - - assert (retries == MAX_WAIT_NAMED_PIPE_RETRY); - - system_printf ("lost connection to cygserver, error = %lu", - GetLastError ()); - - assume_cygserver = false; - - return -1; -} - -#ifndef __INSIDE_CYGWIN__ - -void -transport_layer_pipes::impersonate_client () -{ - assert (_hPipe); - assert (_hPipe != INVALID_HANDLE_VALUE); - assert (_is_accepted_endpoint); - - // verbose: debug_printf ("impersonating pipe %p", _hPipe); - if (_hPipe) - { - assert (_hPipe != INVALID_HANDLE_VALUE); - - if (!ImpersonateNamedPipeClient (_hPipe)) - debug_printf ("Failed to Impersonate the client, (%lu)", - GetLastError ()); - } - // verbose: debug_printf ("I am who you are"); -} - -void -transport_layer_pipes::revert_to_self () -{ - assert (_is_accepted_endpoint); - - RevertToSelf (); - // verbose: debug_printf ("I am who I yam"); -} - -#endif /* !__INSIDE_CYGWIN__ */ diff --git a/winsup/cygwin/cygserver_transport_sockets.cc b/winsup/cygwin/cygserver_transport_sockets.cc deleted file mode 100755 index 6ade14b..0000000 --- a/winsup/cygwin/cygserver_transport_sockets.cc +++ /dev/null @@ -1,387 +0,0 @@ -/* cygserver_transport_sockets.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifdef __OUTSIDE_CYGWIN__ -#include "woutsup.h" -#else -#include "winsup.h" -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#include "cygwin/cygserver_transport.h" -#include "cygwin/cygserver_transport_sockets.h" - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifndef __OUTSIDE_CYGWIN__ - -extern "C" int cygwin_accept (int fd, struct sockaddr *, int *len); -extern "C" int cygwin_bind (int fd, const struct sockaddr *, int len); -extern "C" int cygwin_connect (int fd, const struct sockaddr *, int len); -extern "C" int cygwin_listen (int fd, int backlog); -extern "C" int cygwin_shutdown (int fd, int how); -extern "C" int cygwin_socket (int af, int type, int protocol); - -#else /* __OUTSIDE_CYGWIN__ */ - -#define cygwin_accept(A,B,C) ::accept (A,B,C) -#define cygwin_bind(A,B,C) ::bind (A,B,C) -#define cygwin_connect(A,B,C) ::connect (A,B,C) -#define cygwin_listen(A,B) ::listen (A,B) -#define cygwin_shutdown(A,B) ::shutdown (A,B) -#define cygwin_socket(A,B,C) ::socket (A,B,C) - -#endif /* __OUTSIDE_CYGWIN__ */ - -enum - { - MAX_CONNECT_RETRY = 64 - }; - -transport_layer_sockets::transport_layer_sockets (const int fd) - : _fd (fd), - _addr_len (0), - _is_accepted_endpoint (true), - _is_listening_endpoint (false) -{ - assert (_fd != -1); - - memset (&_addr, '\0', sizeof (_addr)); -} - -transport_layer_sockets::transport_layer_sockets () - : _fd (-1), - _addr_len (0), - _is_accepted_endpoint (false), - _is_listening_endpoint (false) -{ - memset (&_addr, '\0', sizeof (_addr)); - - _addr.sun_family = AF_UNIX; - strcpy (_addr.sun_path, "/tmp/cygdaemo"); // FIXME: $TMP? - _addr_len = SUN_LEN (&_addr); -} - -transport_layer_sockets::~transport_layer_sockets () -{ - close (); -} - -#ifndef __INSIDE_CYGWIN__ - -int -transport_layer_sockets::listen () -{ - assert (_fd == -1); - assert (!_is_accepted_endpoint); - assert (!_is_listening_endpoint); - - debug_printf ("listen () [this = %p]", this); - - struct stat sbuf; - - if (stat (_addr.sun_path, &sbuf) == -1) - { - if (errno != ENOENT) - { - system_printf ("cannot access socket file `%s': %s", - _addr.sun_path, strerror (errno)); - return -1; - } - } - else if (S_ISSOCK (sbuf.st_mode)) - { - // The socket already exists: is a duplicate cygserver running? - - const int newfd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); - - if (newfd == -1) - { - system_printf ("failed to create UNIX domain socket: %s", - strerror (errno)); - return -1; - } - - if (cygwin_connect (newfd, (struct sockaddr *) &_addr, _addr_len) == 0) - { - system_printf ("the daemon is already running"); - (void) cygwin_shutdown (newfd, SHUT_WR); - char buf[BUFSIZ]; - while (::read (newfd, buf, sizeof (buf)) > 0) - {} - (void) ::close (newfd); - return -1; - } - - if (unlink (_addr.sun_path) == -1) - { - system_printf ("failed to remove `%s': %s", - _addr.sun_path, strerror (errno)); - (void) ::close (newfd); - return -1; - } - } - else - { - system_printf ("cannot create socket `%s': File already exists", - _addr.sun_path); - return -1; - } - - _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); - - if (_fd == -1) - { - system_printf ("failed to create UNIX domain socket: %s", - strerror (errno)); - return -1; - } - - if (cygwin_bind (_fd, (struct sockaddr *) &_addr, _addr_len) == -1) - { - const int saved_errno = errno; - close (); - errno = saved_errno; - system_printf ("failed to bind UNIX domain socket `%s': %s", - _addr.sun_path, strerror (errno)); - return -1; - } - - _is_listening_endpoint = true; // i.e. this really means "have bound". - - if (cygwin_listen (_fd, SOMAXCONN) == -1) - { - const int saved_errno = errno; - close (); - errno = saved_errno; - system_printf ("failed to listen on UNIX domain socket `%s': %s", - _addr.sun_path, strerror (errno)); - return -1; - } - - debug_printf ("0 = listen () [this = %p, fd = %d]", this, _fd); - - return 0; -} - -class transport_layer_sockets * -transport_layer_sockets::accept (bool *const recoverable) -{ - assert (_fd != -1); - assert (!_is_accepted_endpoint); - assert (_is_listening_endpoint); - - debug_printf ("accept () [this = %p, fd = %d]", this, _fd); - - struct sockaddr_un client_addr; - socklen_t client_addr_len = sizeof (client_addr); - - const int accept_fd = - cygwin_accept (_fd, (struct sockaddr *) &client_addr, &client_addr_len); - - if (accept_fd == -1) - { - system_printf ("failed to accept connection: %s", strerror (errno)); - switch (errno) - { - case ECONNABORTED: - case EINTR: - case EMFILE: - case ENFILE: - case ENOBUFS: - case ENOMEM: - *recoverable = true; - break; - - default: - *recoverable = false; - break; - } - return NULL; - } - - debug_printf ("%d = accept () [this = %p, fd = %d]", accept_fd, this, _fd); - - return safe_new (transport_layer_sockets, accept_fd); -} - -#endif /* !__INSIDE_CYGWIN__ */ - -void -transport_layer_sockets::close () -{ - debug_printf ("close () [this = %p, fd = %d]", this, _fd); - - if (_is_listening_endpoint) - (void) unlink (_addr.sun_path); - - if (_fd != -1) - { - (void) cygwin_shutdown (_fd, SHUT_WR); - if (!_is_listening_endpoint) - { - char buf[BUFSIZ]; - while (::read (_fd, buf, sizeof (buf)) > 0) - {} - } - (void) ::close (_fd); - _fd = -1; - } - - _is_listening_endpoint = false; -} - -ssize_t -transport_layer_sockets::read (void *const buf, const size_t buf_len) -{ - assert (_fd != -1); - assert (!_is_listening_endpoint); - - assert (buf); - assert (buf_len > 0); - - // verbose: debug_printf ("read (buf = %p, len = %u) [this = %p, fd = %d]", - // buf, buf_len, this, _fd); - - char *read_buf = static_cast<char *> (buf); - size_t read_buf_len = buf_len; - ssize_t res = 0; - - while (read_buf_len != 0 - && (res = ::read (_fd, read_buf, read_buf_len)) > 0) - { - read_buf += res; - read_buf_len -= res; - - assert (read_buf_len >= 0); - } - - if (res != -1) - { - if (res == 0) - errno = EIO; // FIXME? - - res = buf_len - read_buf_len; - } - - if (res != static_cast<ssize_t> (buf_len)) - debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]: %s", - res, buf, buf_len, this, _fd, - (res == -1 ? strerror (errno) : "EOF")); - else - { - // verbose: debug_printf ("%d = read (buf = %p, len = %u) [this = %p, fd = %d]", - // res, buf, buf_len, this, _fd); - } - - return res; -} - -ssize_t -transport_layer_sockets::write (void *const buf, const size_t buf_len) -{ - assert (_fd != -1); - assert (!_is_listening_endpoint); - - assert (buf); - assert (buf_len > 0); - - // verbose: debug_printf ("write (buf = %p, len = %u) [this = %p, fd = %d]", - // buf, buf_len, this, _fd); - - char *write_buf = static_cast<char *> (buf); - size_t write_buf_len = buf_len; - ssize_t res = 0; - - while (write_buf_len != 0 - && (res = ::write (_fd, write_buf, write_buf_len)) > 0) - { - write_buf += res; - write_buf_len -= res; - - assert (write_buf_len >= 0); - } - - if (res != -1) - { - if (res == 0) - errno = EIO; // FIXME? - - res = buf_len - write_buf_len; - } - - if (res != static_cast<ssize_t> (buf_len)) - debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]: %s", - res, buf, buf_len, this, _fd, - (res == -1 ? strerror (errno) : "EOF")); - else - { - // verbose: debug_printf ("%d = write (buf = %p, len = %u) [this = %p, fd = %d]", - // res, buf, buf_len, this, _fd); - } - - return res; -} - -int -transport_layer_sockets::connect () -{ - assert (_fd == -1); - assert (!_is_accepted_endpoint); - assert (!_is_listening_endpoint); - - static bool assume_cygserver = false; - - debug_printf ("connect () [this = %p]", this); - - for (int retries = 0; retries != MAX_CONNECT_RETRY; retries++) - { - _fd = cygwin_socket (AF_UNIX, SOCK_STREAM, 0); - - if (_fd == -1) - { - system_printf ("failed to create UNIX domain socket: %s", - strerror (errno)); - return -1; - } - - if (cygwin_connect (_fd, (struct sockaddr *) &_addr, _addr_len) == 0) - { - assume_cygserver = true; - debug_printf ("0 = connect () [this = %p, fd = %d]", this, _fd); - return 0; - } - - if (!assume_cygserver || errno != ECONNREFUSED) - { - debug_printf ("failed to connect to server: %s", strerror (errno)); - (void) ::close (_fd); - _fd = -1; - return -1; - } - - (void) ::close (_fd); - _fd = -1; - Sleep (0); // Give the server a chance. - } - - debug_printf ("failed to connect to server: %s", strerror (errno)); - return -1; -} diff --git a/winsup/cygwin/dlmalloc.c b/winsup/cygwin/dlmalloc.c index de14fcb..a5a7ff0 100644 --- a/winsup/cygwin/dlmalloc.c +++ b/winsup/cygwin/dlmalloc.c @@ -28,6 +28,21 @@ * malloc_usable_size(P) is equivalent to realloc(P, malloc_usable_size(P)) * * $Log$ + * Revision 1.6 2003/08/31 18:26:58 cgf + * * Makefile.in (MALLOC_OFILES): Always fill in with correct malloc object. + * * configure.in: Fill in MALLOC_OFILES with either debugging or regular malloc. + * * configure: Regenerate. + * * dlmalloc.c: Make various fruitless changes to attempt to get to work. + * * dlmalloc.h: Ditto. + * * malloc.cc (free): Check malloc pool when debugging. + * * path.cc (win32_device_name): Eliminate compiler warning. + * * sigproc.cc (sig_dispatch_pending): Remove use of was_pending. Let + * thisframe.call_signal_handler decide if handler should be called rather than + * using bogus was_pending check. + * * exceptions.cc (interrupt_setup): Remove accidentally checked in debugging + * code. + * * heap.cc (sbrk): Save rounded addess in user_heap_max. + * * Revision 1.5 2001/10/03 03:49:25 cgf * * cygheap.cc (cfree): Remove malloc debugging probe. * * dlmalloc.c (errprint): Remove abort() call which causes interesting error @@ -973,31 +988,31 @@ extern Void_t* sbrk(); #else #ifndef cALLOc -#define cALLOc calloc +#define cALLOc dlcalloc #endif #ifndef fREe -#define fREe free +#define fREe dlfree #endif #ifndef mALLOc -#define mALLOc malloc +#define mALLOc dlmalloc #endif #ifndef mEMALIGn -#define mEMALIGn memalign +#define mEMALIGn dlmemalign #endif #ifndef rEALLOc -#define rEALLOc realloc +#define rEALLOc dlrealloc #endif #ifndef vALLOc -#define vALLOc valloc +#define vALLOc dlvalloc #endif #ifndef pvALLOc -#define pvALLOc pvalloc +#define pvALLOc dlpvalloc #endif #ifndef mALLINFo -#define mALLINFo mallinfo +#define mALLINFo dlmallinfo #endif #ifndef mALLOPt -#define mALLOPt mallopt +#define mALLOPt dlmallopt #endif #endif @@ -1012,7 +1027,6 @@ extern Void_t* sbrk(); #define memalign(align, size) memalign_dbg(align, size, __FILE__, __LINE__) #define valloc(size) valloc_dbg(size, __FILE__, __LINE__) #define pvalloc(size) pvalloc_dbg(size, __FILE__, __LINE__) -#define cfree(p) cfree_dbg(p, __FILE__, __LINE__) #define malloc_trim(pad) malloc_trim_dbg(pad, __FILE__, __LINE__) #define malloc_usable_size(p) malloc_usable_size_dbg(p, __FILE__, __LINE__) #define malloc_stats(void) malloc_stats_dbg(__FILE__, __LINE__) @@ -1027,7 +1041,6 @@ Void_t* calloc_dbg(size_t, size_t, const char *, int); Void_t* memalign_dbg(size_t, size_t, const char *, int); Void_t* valloc_dbg(size_t, const char *, int); Void_t* pvalloc_dbg(size_t, const char *, int); -void cfree_dbg(Void_t*, const char *, int); int malloc_trim_dbg(size_t, const char *, int); size_t malloc_usable_size_dbg(Void_t*, const char *, int); void malloc_stats_dbg(const char *, int); @@ -1041,7 +1054,6 @@ Void_t* calloc_dbg(); Void_t* memalign_dbg(); Void_t* valloc_dbg(); Void_t* pvalloc_dbg(); -void cfree_dbg(); int malloc_trim_dbg(); size_t malloc_usable_size_dbg(); void malloc_stats_dbg(); @@ -1060,7 +1072,6 @@ Void_t* cALLOc(size_t, size_t); Void_t* mEMALIGn(size_t, size_t); Void_t* vALLOc(size_t); Void_t* pvALLOc(size_t); -void cfree(Void_t*); int malloc_trim(size_t); size_t malloc_usable_size(Void_t*); void malloc_stats(void); @@ -1074,7 +1085,6 @@ Void_t* cALLOc(); Void_t* mEMALIGn(); Void_t* vALLOc(); Void_t* pvALLOc(); -void cfree(); int malloc_trim(); size_t malloc_usable_size(); void malloc_stats(); @@ -1102,7 +1112,6 @@ extern "C" { #undef memalign #undef valloc #undef pvalloc -#undef cfree #undef malloc_trim #undef malloc_usable_size #undef malloc_stats @@ -1117,7 +1126,6 @@ Void_t* cALLOc(size_t, size_t); Void_t* mEMALIGn(size_t, size_t); Void_t* vALLOc(size_t); Void_t* pvALLOc(size_t); -void cfree(Void_t*); int malloc_trim(size_t); size_t malloc_usable_size(Void_t*); void malloc_stats(void); @@ -1131,7 +1139,6 @@ Void_t* cALLOc(); Void_t* mEMALIGn(); Void_t* vALLOc(); Void_t* pvALLOc(); -void cfree(); int malloc_trim(); size_t malloc_usable_size(); void malloc_stats(); @@ -1901,7 +1908,6 @@ static void malloc_err(const char *err, mchunkptr p) #undef valloc #undef pvalloc #undef calloc -#undef cfree #undef malloc_trim #undef malloc_usable_size #undef malloc_stats @@ -1959,20 +1965,17 @@ Void_t* realloc_dbg(Void_t *oldmem, size_t bytes, dbgargs) { skelr(Void_t*, realloc(oldmem, bytes)); } Void_t* memalign_dbg(size_t alignment, size_t bytes, dbgargs) { - skelr(Void_t*, memalign(alignment, bytes)); + skelr(Void_t*, dlmemalign(alignment, bytes)); } Void_t* valloc_dbg(size_t bytes, dbgargs) { - skelr(Void_t*, valloc(bytes)); + skelr(Void_t*, dlvalloc(bytes)); } Void_t* pvalloc_dbg(size_t bytes, dbgargs) { - skelr(Void_t*, pvalloc(bytes)); + skelr(Void_t*, dlpvalloc(bytes)); } Void_t* calloc_dbg(size_t n, size_t elem_size, dbgargs) { skelr(Void_t*, calloc(n, elem_size)); } -void cfree_dbg(Void_t *mem, dbgargs) { - skelv(cfree(mem)); -} int malloc_trim_dbg(size_t pad, dbgargs) { skelr(int, malloc_trim(pad)); } @@ -1983,10 +1986,10 @@ void malloc_stats_dbg(dbgargs) { skelv(malloc_stats()); } int mallopt_dbg(int flag, int value, dbgargs) { - skelr(int, mallopt(flag, value)); + skelr(int, dlmallopt(flag, value)); } struct mallinfo mallinfo_dbg(dbgargs) { - skelr(struct mallinfo, mallinfo()); + skelr(struct mallinfo, dlmallinfo()); } #undef skel @@ -3536,24 +3539,6 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; } } -/* - - cfree just calls free. It is needed/defined on some systems - that pair it with calloc, presumably for odd historical reasons. - -*/ - -#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__) -#if __STD_C -void cfree(Void_t *mem) -#else -void cfree(mem) Void_t *mem; -#endif -{ - free(mem); -} -#endif - /* @@ -3580,7 +3565,7 @@ void cfree(mem) Void_t *mem; */ #if __STD_C -int malloc_trim(size_t pad) +int dlmalloc_trim(size_t pad) #else int malloc_trim(pad) size_t pad; #endif @@ -3653,7 +3638,7 @@ int malloc_trim(pad) size_t pad; */ #if __STD_C -size_t malloc_usable_size(Void_t* mem) +size_t dlmalloc_usable_size(Void_t* mem) #else size_t malloc_usable_size(mem) Void_t* mem; #endif @@ -3745,7 +3730,7 @@ static void malloc_update_mallinfo(void) */ -void malloc_stats(void) +void dlmalloc_stats(void) { malloc_update_mallinfo(); fprintf(stderr, "max system bytes = %10u\n", diff --git a/winsup/cygwin/dlmalloc.h b/winsup/cygwin/dlmalloc.h index 15b25db..b8d7ebe 100644 --- a/winsup/cygwin/dlmalloc.h +++ b/winsup/cygwin/dlmalloc.h @@ -8,7 +8,7 @@ * * bbclabel: autogenerated */ - +#define _INCLUDE_MALLOC_H_ 1 void malloc_outofmem(void (*)(void)); @@ -41,19 +41,18 @@ struct mallinfo { #ifdef MALLOC_DEBUG -#define malloc(size) malloc_dbg(size, __FILE__, __LINE__) -#define free(p) free_dbg(p, __FILE__, __LINE__) -#define realloc(p, size) realloc_dbg(p, size, __FILE__, __LINE__) -#define calloc(n, size) calloc_dbg(n, size, __FILE__, __LINE__) -#define memalign(align, size) memalign_dbg(align, size, __FILE__, __LINE__) -#define valloc(size) valloc_dbg(size, __FILE__, __LINE__) -#define pvalloc(size) pvalloc_dbg(size, __FILE__, __LINE__) -#define cfree(p) cfree_dbg(p, __FILE__, __LINE__) -#define malloc_trim(pad) malloc_trim_dbg(pad, __FILE__, __LINE__) -#define malloc_usable_size(p) malloc_usable_size_dbg(p, __FILE__, __LINE__) -#define malloc_stats() malloc_stats_dbg(__FILE__, __LINE__) -#define mallopt(flag, val) mallopt_dbg(flag, val, __FILE__, __LINE__) -#define mallinfo() mallinfo_dbg(__FILE__, __LINE__) +#define dmalloc(size) malloc_dbg(size, __FILE__, __LINE__) +#define dfree(p) free_dbg(p, __FILE__, __LINE__) +#define drealloc(p, size) realloc_dbg(p, size, __FILE__, __LINE__) +#define dcalloc(n, size) calloc_dbg(n, size, __FILE__, __LINE__) +#define dmemalign(align, size) memalign_dbg(align, size, __FILE__, __LINE__) +#define dvalloc(size) valloc_dbg(size, __FILE__, __LINE__) +#define dpvalloc(size) pvalloc_dbg(size, __FILE__, __LINE__) +#define dmalloc_trim(pad) malloc_trim_dbg(pad, __FILE__, __LINE__) +#define dmalloc_usable_size(p) malloc_usable_size_dbg(p, __FILE__, __LINE__) +#define dmalloc_stats() malloc_stats_dbg(__FILE__, __LINE__) +#define dmallopt(flag, val) mallopt_dbg(flag, val, __FILE__, __LINE__) +#define dmallinfo() mallinfo_dbg(__FILE__, __LINE__) #ifdef __cplusplus @@ -66,7 +65,6 @@ void* calloc_dbg(size_t, size_t, const char *, int); void* memalign_dbg(size_t, size_t, const char *, int); void* valloc_dbg(size_t, const char *, int); void* pvalloc_dbg(size_t, const char *, int); -void cfree_dbg(void*, const char *, int); int malloc_trim_dbg(size_t, const char *, int); size_t malloc_usable_size_dbg(void*, const char *, int); void malloc_stats_dbg(const char *, int); @@ -87,7 +85,6 @@ void* calloc(size_t, size_t); void* memalign(size_t, size_t); void* valloc(size_t); void* pvalloc(size_t); -void cfree(void*); int malloc_trim(size_t); size_t malloc_usable_size(void*); void malloc_stats(void); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 075b3cc..c63ed20 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -731,18 +731,6 @@ signal_fixup_after_fork () sigproc_init (); } -void __stdcall -signal_fixup_after_exec () -{ - /* Set up child's signal handlers */ - for (int i = 0; i < NSIG; i++) - { - myself->getsig (i).sa_mask = 0; - if (myself->getsig (i).sa_handler != SIG_IGN) - myself->getsig (i).sa_handler = SIG_DFL; - } -} - static int interrupt_on_return (sigthread *, int, void *, struct sigaction&) __attribute__((regparm(3))); static int interrupt_on_return (sigthread *th, int sig, void *handler, struct sigaction& siga) diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 05dfa79..453eda4 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -264,7 +264,7 @@ fhandler_base::raw_read (void *ptr, size_t& ulen) int prio = 0; /* ditto */ DWORD len = ulen; - (ssize_t) ulen = -1; + ulen = (size_t) -1; if (read_state) { h = GetCurrentThread (); diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index 95fdd12..5157a56 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -139,7 +139,6 @@ sbrk (int n) /* Couldn't allocate memory. Maybe we can reserve some more. Reserve either the maximum of the standard cygwin_shared->heap_chunk_size () or the requested amount. Then attempt to actually allocate it. */ - if ((newbrksize = cygheap->user_heap.chunk) < commitbytes) newbrksize = commitbytes; @@ -147,7 +146,7 @@ sbrk (int n) || VirtualAlloc (cygheap->user_heap.top, newbrksize = commitbytes, MEM_RESERVE, PAGE_NOACCESS)) && VirtualAlloc (cygheap->user_heap.top, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL) { - (char *) cygheap->user_heap.max += newbrksize; + (char *) cygheap->user_heap.max += pround (newbrksize); goto good; } diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index dccff20..e117175 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -92,7 +92,7 @@ enum PID_SPLIT_HEAP = 0x0100, /* Set if the heap has been split, */ /* which means we can't fork again. */ PID_MYSELF = 0x0200, /* Flag that pid is me. */ - PID_UNUSED1 = 0x0400, /* Set if process uses Winsock. */ + PID_NOCLDSTOP = 0x0400, /* Set if no SIGCHLD signal on stop. */ PID_INITIALIZING = 0x0800, /* Set until ready to receive signals. */ PID_USETTY = 0x1000, /* Setting this enables or disables cygwin's */ /* tty support. This is inherited by */ @@ -207,6 +207,7 @@ extern void cygwin_set_impersonation_token (const HANDLE); extern int cygwin32_attach_handle_to_fd (char *, int, HANDLE, mode_t, DWORD); extern int cygwin_attach_handle_to_fd (char *, int, HANDLE, mode_t, DWORD); +#ifdef __CYGWIN__ #include <sys/resource.h> #define TTY_CONSOLE 0x40000000 @@ -250,11 +251,10 @@ struct external_pinfo __uid32_t uid32; __gid32_t gid32; }; - +#endif /*__CYGWIN__*/ #endif /*WINVER*/ #ifdef __cplusplus }; #endif - #endif /* _SYS_CYGWIN_H */ diff --git a/winsup/cygwin/libc/fnmatch.c b/winsup/cygwin/libc/fnmatch.c index 709bc78..b48d9e0 100644 --- a/winsup/cygwin/libc/fnmatch.c +++ b/winsup/cygwin/libc/fnmatch.c @@ -66,9 +66,7 @@ static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp static int rangematch __P((const char *, char, int, char **)); int -fnmatch(pattern, string, flags) - const char *pattern, *string; - int flags; +fnmatch(const char *pattern, const char *string, int flags) { const char *stringstart; char *newp; @@ -168,15 +166,7 @@ fnmatch(pattern, string, flags) } static int -#ifdef __STDC__ rangematch(const char *pattern, char test, int flags, char **newp) -#else -rangematch(pattern, test, flags, newp) - char *pattern; - char test; - int flags; - char **newp; -#endif { int negate, ok; char c, c2; diff --git a/winsup/cygwin/malloc.cc b/winsup/cygwin/malloc.cc index 383a590..7c85bd6 100644 --- a/winsup/cygwin/malloc.cc +++ b/winsup/cygwin/malloc.cc @@ -3744,6 +3744,7 @@ void fREe(mem) Void_t* mem; mchunkptr bck; /* misc temp for linking */ mchunkptr fwd; /* misc temp for linking */ + check_malloc_state(); /* free(0) has no effect */ if (mem != 0) { p = mem2chunk(mem); @@ -3878,6 +3879,7 @@ void fREe(mem) Void_t* mem; #endif } } + check_malloc_state(); } /* diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 36463c3..b888ab6 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -25,6 +25,7 @@ details. */ #include <netdb.h> #define USE_SYS_TYPES_FD_SET #include <winsock2.h> +#include <assert.h> #include "cygerrno.h" #include "security.h" #include "fhandler.h" @@ -381,95 +382,205 @@ set_host_errno () h_errno = NETDB_INTERNAL; } -static void -free_char_list (char **clist) +inline int +DWORD_round (int n) { - if (clist) - { - for (char **cl = clist; *cl; ++cl) - free (*cl); - free (clist); - } + return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD)); } -static char ** -dup_char_list (char **src) +inline int +strlen_round (const char *s) { - char **dst; - int cnt = 0; - - for (char **cl = src; *cl; ++cl) - ++cnt; - if (!(dst = (char **) calloc (cnt + 1, sizeof *dst))) - return NULL; - while (cnt-- > 0) - if (!(dst[cnt] = strdup (src[cnt]))) - return NULL; - return dst; + if (!s) + return 0; + return DWORD_round (strlen (s) + 1); } -#define free_addr_list(addr_list) free_char_list (addr_list) +#pragma pack(push,2) +struct pservent +{ + char *s_name; + char **s_aliases; + short s_port; + char *s_proto; +}; +#pragma pack(pop) -static char ** -dup_addr_list (char **src, unsigned int size) +struct unionent { - char **dst; - int cnt = 0; + char *name; + char **list; + short port_proto_addrtype; + short h_len; + union + { + char *s_proto; + char **h_addr_list; + }; +}; - for (char **cl = src; *cl; ++cl) - ++cnt; - if (!(dst = (char **) calloc (cnt + 1, sizeof *dst))) - return NULL; - while (cnt-- > 0) - { - if (!(dst[cnt] = (char *) malloc (size))) - return NULL; - memcpy (dst[cnt], src[cnt], size); - } - return dst; -} +enum struct_type +{ + is_hostent, is_protoent, is_servent +}; -static void -free_protoent_ptr (struct protoent *&p) +static const char *entnames[] = {"host", "proto", "serv"}; + +/* Generic "dup a {host,proto,serv}ent structure" function. + This is complicated because we need to be able to free the + structure at any point and we can't rely on the pointer contents + being untouched by callers. So, we allocate a chunk of memory + large enough to hold the structure and all of the stuff it points + to then we copy the source into this new block of memory. + The 'unionent' struct is a union of all of the currently used + *ent structure. */ + +#ifdef DEBUGGING +static void * +#else +static inline void * +#endif +dup_ent (void *old, void *src0, struct_type type) { - if (p) + if (old) { - debug_printf ("protoent: %s", p->p_name); - - if (p->p_name) - free (p->p_name); - free_char_list (p->p_aliases); - free ((void *) p); - p = NULL; + debug_printf ("freeing old %sent structure \"%s\" %p\n", entnames[type], + ((unionent *) old)->name, old); + free (old); } -} -static struct protoent * -dup_protoent_ptr (struct protoent *src) -{ - if (!src) + if (!src0) return NULL; - struct protoent *dst = (struct protoent *) calloc (1, sizeof *dst); + unionent *src = (unionent *) src0; + debug_printf ("duping %sent \"%s\", %p", entnames[type], + src ? src->name : "<null!>", src); - if (!dst) - return NULL; + /* Find the size of the raw structure minus any character strings, etc. */ + int sz, struct_sz; + switch (type) + { + case is_protoent: + struct_sz = sizeof (protoent); + break; + case is_servent: + struct_sz = sizeof (servent); + break; + case is_hostent: + struct_sz = sizeof (hostent); + break; + default: + api_fatal ("called with invalid value %d", type); + break; + } - debug_printf ("protoent: %s", src->p_name); + /* Every *ent begins with a name. Calculate it's length. */ + int namelen = strlen_round (src->name); + sz = struct_sz + namelen; - dst->p_proto = src->p_proto; - if (src->p_name && !(dst->p_name = strdup (src->p_name))) - goto out; - if (src->p_aliases && !(dst->p_aliases = dup_char_list (src->p_aliases))) - goto out; + char **av; + /* The next field in every *ent is an argv list of "something". + Calculate the number of components and how much space the + character strings will take. */ + int list_len = 0; + for (av = src->list; av && *av; av++) + { + list_len++; + sz += sizeof (char **) + strlen_round (*av); + } - debug_printf ("protoent: copied %s", dst->p_name); + /* NULL terminate if there actually was a list */ + if (av) + { + sz += sizeof (char **); + list_len++; + } - return dst; + /* Do servent/hostent specific processing */ + int protolen = 0; + int addr_list_len = 0; + if (type == is_servent) + sz += (protolen = strlen_round (src->s_proto)); + else if (type == is_hostent) + { + /* Calculate the length and storage used for h_addr_list */ + for (av = src->h_addr_list; av && *av; av++) + { + addr_list_len++; + sz += sizeof (char **) + DWORD_round (src->h_len); + } + if (av) + { + sz += sizeof (char **); + addr_list_len++; + } + } -out: - free_protoent_ptr (dst); - return NULL; + /* Allocate the storage needed */ + unionent *dst = (unionent *) calloc (1, sz); + + /* Hopefully, this worked. */ + if (dst) + { + /* This field is common to all *ent structures but named differently + in each, of course. */ + dst->port_proto_addrtype = src->port_proto_addrtype; + + /* Copy the name field to dst, using space just beyond the end of + the dst structure. */ + char *dp = ((char *) dst) + struct_sz; + strcpy (dst->name = dp, src->name); + dp += namelen; + + /* Copy the 'list' type to dst, using space beyond end of structure + + storage for name. */ + if (src->list) + { + char **dav = dst->list = (char **) dp; + dp += sizeof (char **) * list_len; + for (av = src->list; av && *av; av++) + { + int len = strlen (*av) + 1; + memcpy (*dav++ = dp, *av, len); + dp += DWORD_round (len); + } + } + + /* Do servent/hostent specific processing. */ + if (type == is_servent) + { + if (src->s_proto) + { + char *s_proto; + /* Windows 95 idiocy. Structure is misaligned on Windows 95. + Kludge around this by trying a different pointer alignment. */ + if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto)) + && !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto))) + s_proto = ((pservent *) src)->s_proto; + else + s_proto = src->s_proto; + strcpy (dst->s_proto = dp, s_proto); + dp += protolen; + } + } + else if (type == is_hostent) + { + /* Transfer h_len and duplicate contents of h_addr_list, using + memory after 'list' allocation. */ + dst->h_len = src->h_len; + char **dav = dst->h_addr_list = (char **) dp; + dp += sizeof (char **) * addr_list_len; + for (av = src->h_addr_list; av && *av; av++) + { + memcpy (*dav++ = dp, *av, src->h_len); + dp += DWORD_round (src->h_len); + } + } + /* Sanity check that we did our bookkeeping correctly. */ + assert ((dp - (char *) dst) == sz); + } + debug_printf ("duped %sent \"%s\", %p", entnames[type], dst ? dst->name : "<null!>", dst); + return dst; } #ifdef _MT_SAFE @@ -484,8 +595,8 @@ cygwin_getprotobyname (const char *p) { if (check_null_str_errno (p)) return NULL; - free_protoent_ptr (protoent_buf); - protoent_buf = dup_protoent_ptr (getprotobyname (p)); + protoent_buf = (protoent *) dup_ent (protoent_buf, getprotobyname (p), + is_protoent); if (!protoent_buf) set_winsock_errno (); @@ -497,8 +608,8 @@ cygwin_getprotobyname (const char *p) extern "C" struct protoent * cygwin_getprotobynumber (int number) { - free_protoent_ptr (protoent_buf); - protoent_buf = dup_protoent_ptr (getprotobynumber (number)); + protoent_buf = (protoent *) dup_ent (protoent_buf, getprotobynumber (number), + is_protoent); if (!protoent_buf) set_winsock_errno (); @@ -828,71 +939,6 @@ cygwin_connect (int fd, const struct sockaddr *name, int namelen) return res; } -static void -free_servent_ptr (struct servent *&p) -{ - if (p) - { - debug_printf ("servent: %s", p->s_name); - - if (p->s_name) - free (p->s_name); - if (p->s_proto) - free (p->s_proto); - free_char_list (p->s_aliases); - free ((void *) p); - p = NULL; - } -} - -#pragma pack(push,2) -struct pservent -{ - char *s_name; - char **s_aliases; - short s_port; - char *s_proto; -}; - -#pragma pack(pop) -static struct servent * -dup_servent_ptr (struct servent *src) -{ - if (!src) - return NULL; - - struct servent *dst = (struct servent *) calloc (1, sizeof *dst); - - if (!dst) - return NULL; - - debug_printf ("servent: %s", src->s_name); - - dst->s_port = src->s_port; - if (src->s_name && !(dst->s_name = strdup (src->s_name))) - goto out; - if (src->s_aliases && !(dst->s_aliases = dup_char_list (src->s_aliases))) - goto out; - char *s_proto; - - if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto)) - && !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto))) - s_proto = ((pservent *) src)->s_proto; - else - s_proto = src->s_proto; - - if (s_proto && !(dst->s_proto = strdup (s_proto))) - goto out; - - debug_printf ("servent: copied %s", dst->s_name); - - return dst; - -out: - free_servent_ptr (dst); - return NULL; -} - #ifdef _MT_SAFE #define servent_buf _reent_winsup ()->_servent_buf #else @@ -909,8 +955,8 @@ cygwin_getservbyname (const char *name, const char *proto) || (proto != NULL && check_null_str_errno (proto))) return NULL; - free_servent_ptr (servent_buf); - servent_buf = dup_servent_ptr (getservbyname (name, proto)); + servent_buf = (servent *) dup_ent (servent_buf, getservbyname (name, proto), + is_servent); if (!servent_buf) set_winsock_errno (); @@ -927,8 +973,8 @@ cygwin_getservbyport (int port, const char *proto) if (proto != NULL && check_null_str_errno (proto)) return NULL; - free_servent_ptr (servent_buf); - servent_buf = dup_servent_ptr (getservbyport (port, proto)); + servent_buf = (servent *) dup_ent (servent_buf, getservbyport (port, proto), + is_servent); if (!servent_buf) set_winsock_errno (); @@ -959,54 +1005,6 @@ cygwin_gethostname (char *name, size_t len) return 0; } -static void -free_hostent_ptr (struct hostent *&p) -{ - if (p) - { - debug_printf ("hostent: %s", p->h_name); - - if (p->h_name) - free ((void *) p->h_name); - free_char_list (p->h_aliases); - free_addr_list (p->h_addr_list); - free ((void *) p); - p = NULL; - } -} - -static struct hostent * -dup_hostent_ptr (struct hostent *src) -{ - if (!src) - return NULL; - - struct hostent *dst = (struct hostent *) calloc (1, sizeof *dst); - - if (!dst) - return NULL; - - debug_printf ("hostent: %s", src->h_name); - - dst->h_addrtype = src->h_addrtype; - dst->h_length = src->h_length; - if (src->h_name && !(dst->h_name = strdup (src->h_name))) - goto out; - if (src->h_aliases && !(dst->h_aliases = dup_char_list (src->h_aliases))) - goto out; - if (src->h_addr_list - && !(dst->h_addr_list = dup_addr_list (src->h_addr_list, src->h_length))) - goto out; - - debug_printf ("hostent: copied %s", dst->h_name); - - return dst; - -out: - free_hostent_ptr (dst); - return NULL; -} - #ifdef _MT_SAFE #define hostent_buf _reent_winsup ()->_hostent_buf #else @@ -1045,8 +1043,8 @@ cygwin_gethostbyname (const char *name) return &tmp; } - free_hostent_ptr (hostent_buf); - hostent_buf = dup_hostent_ptr (gethostbyname (name)); + hostent_buf = (hostent *) dup_ent (hostent_buf, gethostbyname (name), + is_hostent); if (!hostent_buf) { set_winsock_errno (); @@ -1069,8 +1067,9 @@ cygwin_gethostbyaddr (const char *addr, int len, int type) if (__check_invalid_read_ptr_errno (addr, len)) return NULL; - free_hostent_ptr (hostent_buf); - hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type)); + hostent_buf = (hostent *) dup_ent (hostent_buf, + gethostbyaddr (addr, len, type), + is_hostent); if (!hostent_buf) { set_winsock_errno (); diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 26b6aa8..5811497 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1124,7 +1124,7 @@ win32_device_name (const char *src_path, char *win32_path, case FH_SOCKET: char *c; strcpy (win32_path, src_path); - while (c = strchr (win32_path, '/')) + while ((c = strchr (win32_path, '/'))) *c = '\\'; break; case FH_RANDOM: diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 89b683f..e437328 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -36,6 +36,8 @@ enum picom PICOM_CMDLINE = 1 }; +extern struct sigaction *global_sigs; + class _pinfo { public: @@ -110,11 +112,9 @@ public: inline struct sigaction& getsig (int sig) { - return thread2signal ? thread2signal->sigs[sig] : sigs[sig]; + return global_sigs[sig]; } - inline void copysigs (_pinfo *p) {memcpy (sigs, p->sigs, sizeof (sigs));} - inline sigset_t& getsigmask () { return thread2signal ? *thread2signal->sigmask : sig_mask; @@ -143,7 +143,6 @@ public: friend void __stdcall set_myself (pid_t, HANDLE); private: - struct sigaction sigs[NSIG]; sigset_t sig_mask; /* one set for everything to ignore. */ LONG _sigtodo[NSIG + __SIGOFFSET]; pthread *thread2signal; // NULL means thread any other means a pthread diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc index 2fef656..a7edeac 100644 --- a/winsup/cygwin/shm.cc +++ b/winsup/cygwin/shm.cc @@ -1,6 +1,6 @@ /* shm.cc: Single unix specification IPC interface for Cygwin. - Copyright 2002 Red Hat, Inc. + Copyright 2002,2003 Red Hat, Inc. Written by Conrad Scott <conrad.scott@dsl.pipex.com>. Based on code by Robert Collins <robert.collins@hotmail.com>. diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index baad718..2b890dd 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -338,6 +338,12 @@ sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact) if (newact->sa_handler == SIG_DFL && sig == SIGCHLD) sig_clear (sig); set_sigcatchers (oa.sa_handler, newact->sa_handler); + if (sig == SIGCHLD) + { + myself->process_state &= ~PID_NOCLDSTOP; + if (newact->sa_flags & SA_NOCLDSTOP); + myself->process_state |= PID_NOCLDSTOP; + } } if (oldact) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index fd4f295..b14fbac 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -17,6 +17,7 @@ details. */ #include <stdlib.h> #include <sys/cygwin.h> #include <assert.h> +#include <sys/signal.h> #include "cygerrno.h" #include "sync.h" #include "sigproc.h" @@ -48,12 +49,35 @@ details. */ #define NZOMBIES 256 -LONG local_sigtodo[TOTSIGS]; -inline LONG* getlocal_sigtodo (int sig) +static LONG local_sigtodo[TOTSIGS]; +struct sigaction *global_sigs; + +inline LONG * +getlocal_sigtodo (int sig) { return local_sigtodo + __SIGOFFSET + sig; } +void __stdcall +sigalloc () +{ + cygheap->sigs = global_sigs = + (struct sigaction *) ccalloc (HEAP_SIGS, NSIG, sizeof (struct sigaction)); +} + +void __stdcall +signal_fixup_after_exec () +{ + global_sigs = cygheap->sigs; + /* Set up child's signal handlers */ + for (int i = 0; i < NSIG; i++) + { + myself->getsig (i).sa_mask = 0; + if (myself->getsig (i).sa_handler != SIG_IGN) + myself->getsig (i).sa_handler = SIG_DFL; + } +} + /* * Global variables */ @@ -300,7 +324,6 @@ proc_subproc (DWORD what, DWORD val) vchild->sid = myself->sid; vchild->ctty = myself->ctty; vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY); - vchild->copysigs (myself); sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p", vchild->pid, nchildren, vchild->dwProcessId, @@ -540,12 +563,11 @@ sig_dispatch_pending () sigframe thisframe (mainthread); - int was_pending = pending_signals; #ifdef DEBUGGING - sigproc_printf ("pending_signals %d", was_pending); + sigproc_printf ("pending_signals %d", pending_signals); #endif - if (!was_pending) + if (!pending_signals) #ifdef DEBUGGING sigproc_printf ("no need to wake anything up"); #else @@ -559,10 +581,7 @@ sig_dispatch_pending () #endif } - if (was_pending) - thisframe.call_signal_handler (); - - return was_pending; + return thisframe.call_signal_handler (); } /* Message initialization. Called from dll_crt0_1 diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 5cedaea..360ae8b 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -120,6 +120,7 @@ int __stdcall sig_send (_pinfo *, int, DWORD ebp = (DWORD) __builtin_frame_addre void __stdcall signal_fixup_after_fork (); void __stdcall signal_fixup_after_exec (); void __stdcall wait_for_sigthread (); +void __stdcall sigalloc (); extern char myself_nowait_dummy[]; extern char myself_nowait_nonmain_dummy[]; diff --git a/winsup/cygwin/threaded_queue.cc b/winsup/cygwin/threaded_queue.cc deleted file mode 100755 index ba0fe41..0000000 --- a/winsup/cygwin/threaded_queue.cc +++ /dev/null @@ -1,408 +0,0 @@ -/* threaded_queue.cc - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "woutsup.h" - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/types.h> -#include <stdlib.h> -#include "threaded_queue.h" - -/*****************************************************************************/ - -/* queue_request */ - -queue_request::~queue_request () -{} - -/*****************************************************************************/ - -/* threaded_queue */ - -threaded_queue::threaded_queue (const size_t initial_workers) - : _workers_count (0), - _running (false), - _submitters_head (NULL), - _requests_count (0), - _requests_head (NULL), - _requests_sem (NULL) -{ - InitializeCriticalSection (&_queue_lock); - - // This semaphore's count is the number of requests on the queue. - // The maximum count (129792) is calculated as MAXIMUM_WAIT_OBJECTS - // multiplied by max. threads per process (2028?), which is (a few) - // more requests than could ever be pending with the current design. - - _requests_sem = CreateSemaphore (NULL, // SECURITY_ATTRIBUTES - 0, // Initial count - 129792, // Maximum count - NULL); // Anonymous - - if (!_requests_sem) - { - system_printf (("failed to create the request queue semaphore, " - "error = %lu"), - GetLastError ()); - abort (); - } - - create_workers (initial_workers); -} - -threaded_queue::~threaded_queue () -{ - if (_running) - stop (); - - debug_printf ("deleting all pending queue requests"); - queue_request *reqptr = _requests_head; - while (reqptr) - { - queue_request *const ptr = reqptr; - reqptr = reqptr->_next; - safe_delete (ptr); - } - - DeleteCriticalSection (&_queue_lock); - if (_requests_sem) - (void) CloseHandle (_requests_sem); -} - -/* FIXME: return success or failure rather than quitting */ -void -threaded_queue::add_submission_loop (queue_submission_loop *const submitter) -{ - assert (this); - assert (submitter); - assert (submitter->_queue == this); - assert (!submitter->_next); - - submitter->_next = - TInterlockedExchangePointer (&_submitters_head, submitter); - - if (_running) - submitter->start (); -} - -bool -threaded_queue::start () -{ - EnterCriticalSection (&_queue_lock); - const bool was_running = _running; - _running = true; - queue_submission_loop *loopptr = _submitters_head; - LeaveCriticalSection (&_queue_lock); - - if (!was_running) - { - debug_printf ("starting all queue submission loops"); - - while (loopptr) - { - queue_submission_loop *const ptr = loopptr; - loopptr = loopptr->_next; - ptr->start (); - } - } - - return was_running; -} - -bool -threaded_queue::stop () -{ - EnterCriticalSection (&_queue_lock); - const bool was_running = _running; - _running = false; - queue_submission_loop *loopptr = _submitters_head; - LeaveCriticalSection (&_queue_lock); - - if (was_running) - { - debug_printf ("stopping all queue submission loops"); - while (loopptr) - { - queue_submission_loop *const ptr = loopptr; - loopptr = loopptr->_next; - ptr->stop (); - } - - ReleaseSemaphore (_requests_sem, _workers_count, NULL); - while (_workers_count) - { - debug_printf (("waiting for worker threads to terminate: " - "%lu still running"), - _workers_count); - Sleep (1000); - } - debug_printf ("all worker threads have terminated"); - } - - return was_running; -} - -/* FIXME: return success or failure */ -void -threaded_queue::add (queue_request *const therequest) -{ - assert (this); - assert (therequest); - assert (!therequest->_next); - - if (!_workers_count) - { - system_printf ("warning: no worker threads to handle request!"); - // FIXME: And then what? - } - - EnterCriticalSection (&_queue_lock); - if (!_requests_head) - _requests_head = therequest; - else - { - /* Add to the queue end. */ - queue_request *reqptr = _requests_head; - for (; reqptr->_next; reqptr = reqptr->_next) - {} - assert (reqptr); - assert (!reqptr->_next); - reqptr->_next = therequest; - } - - _requests_count += 1; - assert (_requests_count > 0); - LeaveCriticalSection (&_queue_lock); - - (void) ReleaseSemaphore (_requests_sem, 1, NULL); -} - -/*static*/ DWORD WINAPI -threaded_queue::start_routine (const LPVOID lpParam) -{ - class threaded_queue *const queue = (class threaded_queue *) lpParam; - assert (queue); - - queue->worker_loop (); - - const long count = InterlockedDecrement (&queue->_workers_count); - assert (count >= 0); - - if (queue->_running) - debug_printf ("worker loop has exited; thread about to terminate"); - - return 0; -} - -/* Called from the constructor: so no need to be thread-safe until the - * worker threads start to be created; thus the interlocked increment - * of the `_workers_count' field. - */ - -void -threaded_queue::create_workers (const size_t initial_workers) -{ - assert (initial_workers > 0); - - for (unsigned int i = 0; i != initial_workers; i++) - { - const long count = InterlockedIncrement (&_workers_count); - assert (count > 0); - - DWORD tid; - const HANDLE hThread = - CreateThread (NULL, 0, start_routine, this, 0, &tid); - - if (!hThread) - { - system_printf ("failed to create thread, error = %lu", - GetLastError ()); - abort (); - } - - (void) CloseHandle (hThread); - } -} - -void -threaded_queue::worker_loop () -{ - while (true) - { - const DWORD rc = WaitForSingleObject (_requests_sem, INFINITE); - if (rc == WAIT_FAILED) - { - system_printf ("wait for request semaphore failed, error = %lu", - GetLastError ()); - return; - } - assert (rc == WAIT_OBJECT_0); - - EnterCriticalSection (&_queue_lock); - if (!_running) - { - LeaveCriticalSection (&_queue_lock); - return; - } - - assert (_requests_head); - queue_request *const reqptr = _requests_head; - _requests_head = reqptr->_next; - - _requests_count -= 1; - assert (_requests_count >= 0); - LeaveCriticalSection (&_queue_lock); - - assert (reqptr); - reqptr->process (); - safe_delete (reqptr); - } -} - -/*****************************************************************************/ - -/* queue_submission_loop */ - -queue_submission_loop::queue_submission_loop (threaded_queue *const queue, - const bool ninterruptible) - : _running (false), - _interrupt_event (NULL), - _queue (queue), - _interruptible (ninterruptible), - _hThread (NULL), - _tid (0), - _next (NULL) -{ - if (_interruptible) - { - // verbose: debug_printf ("creating an interruptible processing thread"); - - _interrupt_event = CreateEvent (NULL, // SECURITY_ATTRIBUTES - FALSE, // Auto-reset - FALSE, // Initially non-signalled - NULL); // Anonymous - - if (!_interrupt_event) - { - system_printf ("failed to create interrupt event, error = %lu", - GetLastError ()); - abort (); - } - } -} - -queue_submission_loop::~queue_submission_loop () -{ - if (_running) - stop (); - if (_interrupt_event) - (void) CloseHandle (_interrupt_event); - if (_hThread) - (void) CloseHandle (_hThread); -} - -bool -queue_submission_loop::start () -{ - assert (this); - assert (!_hThread); - - const bool was_running = _running; - - if (!was_running) - { - _running = true; - - _hThread = CreateThread (NULL, 0, start_routine, this, 0, &_tid); - if (!_hThread) - { - system_printf ("failed to create thread, error = %lu", - GetLastError ()); - abort (); - } - } - - return was_running; -} - -bool -queue_submission_loop::stop () -{ - assert (this); - assert (_hThread && _hThread != INVALID_HANDLE_VALUE); - - const bool was_running = _running; - - if (_running) - { - _running = false; - - if (_interruptible) - { - assert (_interrupt_event - && _interrupt_event != INVALID_HANDLE_VALUE); - - SetEvent (_interrupt_event); - - if (WaitForSingleObject (_hThread, 1000) == WAIT_TIMEOUT) - { - system_printf (("request loop thread %lu failed to shutdown " - "when asked politely: about to get heavy"), - _tid); - - if (!TerminateThread (_hThread, 0)) - { - system_printf (("failed to kill request loop thread %lu" - ", error = %lu"), - _tid, GetLastError ()); - abort (); - } - } - } - else - { - // FIXME: could wait to see if the request loop notices that - // the submission loop is no longer running and shuts down - // voluntarily. - - debug_printf ("killing request loop thread %lu", _tid); - - if (!TerminateThread (_hThread, 0)) - system_printf (("failed to kill request loop thread %lu" - ", error = %lu"), - _tid, GetLastError ()); - } - } - - return was_running; -} - -/*static*/ DWORD WINAPI -queue_submission_loop::start_routine (const LPVOID lpParam) -{ - class queue_submission_loop *const submission_loop = - (class queue_submission_loop *) lpParam; - assert (submission_loop); - - submission_loop->request_loop (); - - debug_printf ("submission loop has exited; thread about to terminate"); - - submission_loop->stop (); - - return 0; -} - -/*****************************************************************************/ diff --git a/winsup/cygwin/threaded_queue.h b/winsup/cygwin/threaded_queue.h deleted file mode 100755 index 5b6fddc..0000000 --- a/winsup/cygwin/threaded_queue.h +++ /dev/null @@ -1,127 +0,0 @@ -/* threaded_queue.h - - Copyright 2001, 2002 Red Hat Inc. - - Written by Robert Collins <rbtcollins@hotmail.com> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#ifndef _THREADED_QUEUE_ -#define _THREADED_QUEUE_ - -/*****************************************************************************/ - -/* a specific request */ - -class queue_request -{ -public: - queue_request *_next; - - queue_request () : _next (NULL) {} - virtual ~queue_request (); - - virtual void process () = 0; -}; - -/*****************************************************************************/ - -/* a queue to allocate requests from n submission loops to x worker threads */ - -class queue_submission_loop; - -class threaded_queue -{ -public: - threaded_queue (size_t initial_workers = 1); - ~threaded_queue (); - - void add_submission_loop (queue_submission_loop *); - - bool running () const { return _running; } - - bool start (); - bool stop (); - - void add (queue_request *); - -private: - long _workers_count; - bool _running; - - queue_submission_loop *_submitters_head; - - long _requests_count; // Informational only. - queue_request *_requests_head; - - CRITICAL_SECTION _queue_lock; - HANDLE _requests_sem; // == _requests_count - - static DWORD WINAPI start_routine (LPVOID /* this */); - - void create_workers (size_t initial_workers); - void worker_loop (); -}; - -/*****************************************************************************/ - -/* parameters for a request finding and submitting loop */ - -class queue_submission_loop -{ - friend class threaded_queue; - -public: - queue_submission_loop (threaded_queue *, bool ninterruptible); - virtual ~queue_submission_loop (); - - bool start (); - bool stop (); - - threaded_queue *queue () { return _queue; }; - -protected: - bool _running; - HANDLE _interrupt_event; - threaded_queue *const _queue; - -private: - bool _interruptible; - HANDLE _hThread; - DWORD _tid; - queue_submission_loop *_next; - - static DWORD WINAPI start_routine (LPVOID /* this */); - virtual void request_loop () = 0; -}; - -#ifdef __cplusplus - -/*---------------------------------------------------------------------------* - * Some type-safe versions of the various interlocked functions. - *---------------------------------------------------------------------------*/ - -template <typename T> T * -TInterlockedExchangePointer (T **lvalue, T *rvalue) -{ - return reinterpret_cast<T *> - (InterlockedExchangePointer (reinterpret_cast<void **> (lvalue), - reinterpret_cast<void *> (rvalue))); -} - -template <typename T> T * -TInterlockedCompareExchangePointer (T **lvalue, T *rvalue1, T *rvalue2) -{ - return reinterpret_cast<T *> - (InterlockedCompareExchangePointer (reinterpret_cast<void **> (lvalue), - reinterpret_cast<void *> (rvalue1), - reinterpret_cast<void *> (rvalue2))); -} - -#endif /* __cplusplus */ - -#endif /* _THREADED_QUEUE_ */ |