diff options
author | rbcollins <rbcollins> | 2001-09-30 13:56:37 +0000 |
---|---|---|
committer | rbcollins <rbcollins> | 2001-09-30 13:56:37 +0000 |
commit | 6f0cb845d96e289c7a79be32562a605b9a33acbb (patch) | |
tree | fe6f46385718ea9b4af2edc95150c0e34fca20cb | |
parent | f2d986607e1da33cb0dd6a534fbdb96fe0bd13a6 (diff) | |
download | gdb-6f0cb845d96e289c7a79be32562a605b9a33acbb.tar.gz |
Sun Sep 30 23:41:00 2001 Robert Collins <rbtcollins@hotmail.com>
* Makefile.in: Add cygserver_process.o to cygserver.exe.
* cygserver.cc: Include signal.h and cygwin_version.h.
Define debug_printf as a macro.
Define DEBUG to a value.
(client_request_attach_tty::serve): Add beginning of process cache support.
Change from #ifdef DEBUG to work with new DEBUG style.
(client_request_get_version::serve): Add beginning of process cache support.
(class server_request): New prototype for support of process cache.
(class queue_process_param): New class to allow request loop threading.
(class server_request_queue): Add beginning of process cache support.
Allow request loop threading.
(request_loop): Thread function for request loops.
(server_request_queue::process_requests): Initiator for threaded request loops.
(client_request_shutdown::serve): Add beginning of process cache support.
(server_request::server_request): Ditto.
(server_request::process): Use debug_printf. Add beginning of process cache support.
(server_request_queue::cleanup): Kill off any request loop threads.
(server_request_queue::add): Add beginning of process cache support.
(handle_signal): Trigger a shutdown.
(main): Print out some useful info at startup - version, date time.
Add process cache support.
Spawn a separate thread for the transport request loop, thus allowing concurrent
support for multiple transports.
* cygserver_client.cc (client_request_get_version::serve): Add process cache support.
(client_request_attach_tty::serve): Add process cache support.
(client_request_shutdown::serve): Add process cache support.
* cygsserver_process.cc: New file with the process cache support.
* cygserver_shm.cc: Redefine debug_printf to allow conditional output.
* cygwin.din: Export shmdt().
* shm.cc: Run indent.
Update FIXME's.
(shmdt): New function.
* include/cygwin/cygserver.h (class client_request): Add process cache support.
(class client_request_get_version): Ditto.
(class client_request_shutdown): Ditto.
(class client_request_attach_tty): Ditto.
* include/cygwin/cygserver_process.h: New header for process cache support.
-rw-r--r-- | winsup/cygwin/ChangeLog | 40 | ||||
-rw-r--r-- | winsup/cygwin/Makefile.in | 2 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver.cc | 190 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_client.cc | 6 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_process.cc | 72 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_shm.cc | 9 | ||||
-rw-r--r-- | winsup/cygwin/cygwin.din | 1 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver.h | 8 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver_process.h | 43 | ||||
-rw-r--r-- | winsup/cygwin/shm.cc | 166 |
10 files changed, 414 insertions, 123 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 828dffd9e00..bc5efb63130 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,43 @@ +Sun Sep 30 23:41:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * Makefile.in: Add cygserver_process.o to cygserver.exe. + * cygserver.cc: Include signal.h and cygwin_version.h. + Define debug_printf as a macro. + Define DEBUG to a value. + (client_request_attach_tty::serve): Add beginning of process cache support. + Change from #ifdef DEBUG to work with new DEBUG style. + (client_request_get_version::serve): Add beginning of process cache support. + (class server_request): New prototype for support of process cache. + (class queue_process_param): New class to allow request loop threading. + (class server_request_queue): Add beginning of process cache support. + Allow request loop threading. + (request_loop): Thread function for request loops. + (server_request_queue::process_requests): Initiator for threaded request loops. + (client_request_shutdown::serve): Add beginning of process cache support. + (server_request::server_request): Ditto. + (server_request::process): Use debug_printf. Add beginning of process cache support. + (server_request_queue::cleanup): Kill off any request loop threads. + (server_request_queue::add): Add beginning of process cache support. + (handle_signal): Trigger a shutdown. + (main): Print out some useful info at startup - version, date time. + Add process cache support. + Spawn a separate thread for the transport request loop, thus allowing concurrent + support for multiple transports. + * cygserver_client.cc (client_request_get_version::serve): Add process cache support. + (client_request_attach_tty::serve): Add process cache support. + (client_request_shutdown::serve): Add process cache support. + * cygsserver_process.cc: New file with the process cache support. + * cygserver_shm.cc: Redefine debug_printf to allow conditional output. + * cygwin.din: Export shmdt(). + * shm.cc: Run indent. + Update FIXME's. + (shmdt): New function. + * include/cygwin/cygserver.h (class client_request): Add process cache support. + (class client_request_get_version): Ditto. + (class client_request_shutdown): Ditto. + (class client_request_attach_tty): Ditto. + * include/cygwin/cygserver_process.h: New header for process cache support. + Sun Sep 30 8:52:00 2001 Robert Collins <rbtcollins@hotmail.com> * include/cygwin/cygserver_transport.h: Add copyright header. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 6ab06144e09..dc3aa8f3030 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -239,7 +239,7 @@ cygserver_client_outside.o: cygserver_client.cc cygserver_shm_outside.o: cygserver_shm.cc $(COMPILE_CXX) -D__OUTSIDE_CYGWIN__ -o $@ $< -cygserver.exe: cygserver.o cygserver_shm_outside.o cygserver_transport_outside.o cygserver_transport_pipes_outside.o cygserver_transport_sockets_outside.o cygserver_client_outside.o wincap.o smallprint.o +cygserver.exe: cygserver.o cygserver_shm_outside.o cygserver_transport_outside.o cygserver_transport_pipes_outside.o cygserver_transport_sockets_outside.o cygserver_client_outside.o cygserver_process.o wincap.o version.o smallprint.o $(CXX) -o $@ $^ #ifdef VERBOSE # $(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc index 8f30d90dda3..083df06af88 100755 --- a/winsup/cygwin/cygserver.cc +++ b/winsup/cygwin/cygserver.cc @@ -17,16 +17,22 @@ #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> +#include <signal.h> #include "wincap.h" +#include "cygwin_version.h" #include "getopt.h" #include "cygwin/cygserver_transport.h" #include "cygwin/cygserver_transport_pipes.h" #include "cygwin/cygserver_transport_sockets.h" +#include "cygwin/cygserver_process.h" #include "cygwin/cygserver.h" #include "cygserver_shm.h" +/* for quieter operation, set to 0 */ +#define DEBUG 0 +#define debug_printf if (DEBUG) printf GENERIC_MAPPING access_mapping; class transport_layer_base *transport; @@ -157,7 +163,7 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process, } void -client_request_attach_tty::serve(transport_layer_base *conn) +client_request_attach_tty::serve(transport_layer_base *conn, class process_cache *cache) { HANDLE from_process_handle = NULL; HANDLE to_process_handle = NULL; @@ -170,8 +176,8 @@ client_request_attach_tty::serve(transport_layer_base *conn) return; } -#ifdef DEBUG - printf ("%d:(%d,%d) -> %d\n", req.master_pid, +#if DEBUG + printf ("%ld:(%p,%p) -> %ld\n", req.master_pid, req.from_master, req.to_master, req.pid); #endif @@ -226,8 +232,8 @@ client_request_attach_tty::serve(transport_layer_base *conn) } } -#ifdef DEBUG - printf ("%d -> %d(%d,%d)\n", req.master_pid, req.pid, +#if DEBUG + printf ("%ld -> %ld(%p,%p)\n", req.master_pid, req.pid, req.from_master, req.to_master); #endif @@ -243,7 +249,7 @@ out: } void -client_request_get_version::serve(transport_layer_base *conn) +client_request_get_version::serve(transport_layer_base *conn, class process_cache *cache) { if (header.cb != sizeof (version)) { @@ -261,11 +267,22 @@ class server_request { public: class server_request *next; - server_request (transport_layer_base *newconn); + server_request (transport_layer_base *newconn, class process_cache *newcache); void process (); private: char request_buffer [MAX_REQUEST_SIZE]; transport_layer_base *conn; + class process_cache *cache; +}; + +class queue_process_param +{ + public: + class queue_process_param * next; + class server_request_queue *queue; + transport_layer_base *transport; + HANDLE hThread; + DWORD tid; }; class server_request_queue @@ -277,14 +294,56 @@ class server_request_queue bool active; unsigned int initial_workers; unsigned int running; + class process_cache *cache; void create_workers (); void cleanup (); + void process_requests (transport_layer_base *transport); void add (transport_layer_base *conn); + private: + class queue_process_param * process_head; }; class server_request_queue request_queue; +DWORD WINAPI +request_loop (LPVOID LpParam) +{ + class queue_process_param *params = (queue_process_param *) LpParam; + class server_request_queue *queue = params->queue; + class transport_layer_base * transport = params->transport; + while (queue->active) + { + transport_layer_base * new_conn = transport->accept (); + /* 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 + */ + if (new_conn && queue->active) + queue->add (new_conn); + } + return 0; +} + +/* TODO: check we are not being asked to service a already serviced transport */ void -client_request_shutdown::serve (transport_layer_base *conn) +server_request_queue::process_requests (transport_layer_base *transport) +{ + class queue_process_param *params; + params = new queue_process_param; + params->transport = transport; + params->queue = this; + params->hThread = CreateThread (NULL, 0, request_loop, params, 0, ¶ms->tid); + if (params->hThread == NULL) + { + printf ("Failed to create thread (%lu), terminating\n", GetLastError ()); + delete params; + exit (1); + } + params->next = (queue_process_param *) InterlockedExchangePointer (&process_head, params); +} + +void +client_request_shutdown::serve (transport_layer_base *conn, class process_cache *cache) { /* FIXME: link upwards, and then this becomes a trivial method call to * only shutdown _this queue_ @@ -293,9 +352,10 @@ client_request_shutdown::serve (transport_layer_base *conn) request_queue.active=false; } -server_request::server_request (transport_layer_base *newconn) +server_request::server_request (transport_layer_base *newconn, class process_cache *newcache) { conn = newconn; + cache = newcache; next = NULL; } @@ -305,7 +365,7 @@ server_request::process () ssize_t bytes_read, bytes_written; struct request_header* req_ptr = (struct request_header*) &request_buffer; client_request *req = NULL; - printf ("about to read\n"); + debug_printf ("about to read\n"); bytes_read = conn->read (request_buffer, sizeof (struct request_header)); if (bytes_read != sizeof (struct request_header)) @@ -313,7 +373,7 @@ server_request::process () printf ("error reading from connection (%lu)\n", GetLastError ()); goto out; } - printf ("got header (%ld)\n", bytes_read); + debug_printf ("got header (%ld)\n", bytes_read); switch (req_ptr->req_id) { @@ -328,12 +388,12 @@ server_request::process () default: req = new client_request (CYGSERVER_REQUEST_INVALID); req->header.error_code = ENOSYS; - printf ("Bad client request - returning ENOSYS\n"); + debug_printf ("Bad client request - returning ENOSYS\n"); } if (req->header.cb != req_ptr->cb) { - printf ("Mismatch in request buffer sizes\n"); + debug_printf ("Mismatch in request buffer sizes\n"); goto out; } @@ -343,25 +403,26 @@ server_request::process () bytes_read = conn->read (req->buffer, req->header.cb); if (bytes_read != req->header.cb) { - printf ("error reading from connection (%lu)\n", GetLastError ()); + debug_printf ("error reading from connection (%lu)\n", GetLastError ()); goto out; } - printf ("got body (%ld)\n",bytes_read); + debug_printf ("got body (%ld)\n",bytes_read); } /* this is not allowed to fail. We must return ENOSYS at a minimum to the client */ - req->serve (conn); + req->serve (conn, cache); if ((bytes_written = conn->write ((char *)&req->header, sizeof (req->header))) - != sizeof(req->header) || - (bytes_written = conn->write (req->buffer, req->header.cb)) != req->header.cb) + != sizeof(req->header) || (req->header.cb && + (bytes_written = conn->write (req->buffer, req->header.cb)) != req->header.cb)) { req->header.error_code = -1; printf ("error writing to connection (%lu)\n", GetLastError ()); goto out; } - printf("Sent reply, size (%ld)\n",bytes_written); + debug_printf("Sent reply, size (%ld)\n",bytes_written); + printf ("."); out: conn->close (); @@ -441,6 +502,25 @@ server_request_queue::cleanup () { /* harvest the threads */ active = false; + /* kill the request processing loops */ + queue_process_param * reqloop; + /* make sure we don't race with a incoming request creation */ + EnterCriticalSection (&queuelock); + reqloop = (queue_process_param *) InterlockedExchangePointer (&process_head, NULL); + while (reqloop) + { + printf ("killing request loop thread %ld\n", reqloop->tid); + int rc; + if (!(rc = TerminateThread (reqloop->hThread, 0))) + { + printf ("error shutting down request loop worker thread\n"); + } + CloseHandle (reqloop->hThread); + queue_process_param *t = reqloop; + reqloop = reqloop->next; + delete t; + } + LeaveCriticalSection (&queuelock); if (!running) return; printf ("Waiting for current connections to terminate\n"); @@ -467,7 +547,7 @@ server_request_queue::add (transport_layer_base *conn) server_request * listrequest; if (!request) { - request = new server_request (conn); + request = new server_request (conn, cache); listrequest = request; } else @@ -476,13 +556,24 @@ server_request_queue::add (transport_layer_base *conn) listrequest = request; while (listrequest->next) listrequest = listrequest->next; - listrequest->next = new server_request (conn); + listrequest->next = new server_request (conn, cache); listrequest = listrequest->next; } PulseEvent (event); LeaveCriticalSection (&queuelock); } +void +handle_signal (int signal) +{ + /* any signal makes us die :} */ + /* FIXME: link upwards, and then this becomes a trivial method call to + * only shutdown _this queue_ + */ + /* tell the main thread to shutdown */ + request_queue.active=false; +} + struct option longopts[] = { {"shutdown", no_argument, NULL, 's'}, {0, no_argument, NULL, 0} @@ -528,21 +619,52 @@ main (int argc, char **argv) exit(0); } - transport->listen (); - request_queue.initial_workers = 10; - request_queue.create_workers(); - while (request_queue.active) + char version[200]; + /* Cygwin dll release */ + snprintf (version, 200, "%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); + setbuf (stdout, NULL); + printf ("daemon version %s starting up", version); + if (signal (SIGQUIT, handle_signal) == SIG_ERR) { - transport_layer_base * new_conn = transport->accept (); - /* 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 - */ - if (new_conn && request_queue.active) - request_queue.add (new_conn); + printf ("\ncould not install signal handler (%d)- aborting startup\n", errno); + exit (1); } - printf ("No longer accepting requests.\n"); + printf ("."); + transport->listen (); + printf ("."); + class process_cache cache; + request_queue.initial_workers = 10; + request_queue.cache = &cache; + request_queue.create_workers (); + printf ("."); + request_queue.process_requests (transport); + 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); + */ + while (1 && request_queue.active) + sleep (1); + printf ("\nShutdown request recieved. No longer accepting requests.\n"); request_queue.cleanup (); + printf ("All pending requests processed\n"); transport->close (); + printf ("request port closed\n"); + printf ("daemon shutdown\n"); } diff --git a/winsup/cygwin/cygserver_client.cc b/winsup/cygwin/cygserver_client.cc index 266687e262f..ef9b8706770 100755 --- a/winsup/cygwin/cygserver_client.cc +++ b/winsup/cygwin/cygserver_client.cc @@ -42,7 +42,7 @@ client_request_get_version::client_request_get_version () : client_request (CYGS #ifdef __INSIDE_CYGWIN__ void -client_request_get_version::serve (transport_layer_base *conn) +client_request_get_version::serve (transport_layer_base *conn, class process_cache *cache) { } #endif @@ -69,7 +69,7 @@ client_request_attach_tty::client_request_attach_tty (DWORD npid, DWORD nmaster_ #ifdef __INSIDE_CYGWIN__ void -client_request_attach_tty::serve (transport_layer_base *conn) +client_request_attach_tty::serve (transport_layer_base *conn, class process_cache *cache) { } #endif @@ -82,7 +82,7 @@ client_request_shutdown::client_request_shutdown () : client_request (CYGSERVER_ #ifdef __INSIDE_CYGWIN__ void -client_request_shutdown::serve (transport_layer_base *conn) +client_request_shutdown::serve (transport_layer_base *conn, class process_cache *cache) { } #endif diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc new file mode 100755 index 00000000000..8ec1c03e3d6 --- /dev/null +++ b/winsup/cygwin/cygserver_process.cc @@ -0,0 +1,72 @@ +/* cygserver_process.cc + + Copyright 2001 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 <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <windows.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include "wincap.h" +#include <cygwin/cygserver_process.h> + +#define debug_printf if (DEBUG) printf +#define DEBUG 1 + +/* process cache */ +process_cache::process_cache () : head (NULL) +{ +} + +class process * +process_cache::process (long pid) +{ + class process_entry *entry = head; + while (entry && entry->process.winpid != pid) + entry = entry->next; + if (!entry) + return NULL; + return &entry->process; +} + +/* process cache entries */ +process_entry::process_entry (long pid) : next (NULL), process (pid) +{ +} + +/* process's */ +process::process (long pid) : winpid (pid) +{ + thehandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); + debug_printf ("Got handle %p for new cache process %ld\n", thehandle, pid); +} + +HANDLE +process::handle () +{ + unsigned long exitstate; + bool err = GetExitCodeProcess (thehandle, &exitstate); + if (!err) + { + /* FIXME: */ + thehandle = INVALID_HANDLE_VALUE; + return INVALID_HANDLE_VALUE; + } + if (exitstate != STILL_ACTIVE) + { + /* FIXME: call the cleanup list */ + thehandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid); + /* FIXME: what if this fails */ + } + return thehandle; +} diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc index 97246f0e389..e4da727e63c 100755 --- a/winsup/cygwin/cygserver_shm.cc +++ b/winsup/cygwin/cygserver_shm.cc @@ -1,4 +1,4 @@ -/* shm.cc: Single unix specification IPC interface for Cygwin +/* cygserver_shm.cc: Single unix specification IPC interface for Cygwin Copyright 2001 Red Hat, Inc. @@ -18,8 +18,9 @@ #endif #ifndef __INSIDE_CYGWIN__ +#define DEBUG 0 #define system_printf printf -#define debug_printf printf +#define debug_printf if (DEBUG) printf #define api_fatal printf #include <stdio.h> #include <windows.h> @@ -293,8 +294,8 @@ client_request_shm_get::serve (transport_layer_base * conn) shmname = stringbuf; snprintf (stringbuf1, 29, "CYGWINSHMD0x%0qx", parameters.in.key); shmaname = stringbuf1; -debug_printf ("system id strings are \n%s\n%s\n",shmname,shmaname); -debug_printf ("key input value is 0x%0qx\n", parameters.in.key); + debug_printf ("system id strings are \n%s\n%s\n",shmname,shmaname); + debug_printf ("key input value is 0x%0qx\n", parameters.in.key); } /* attempt to open the key */ diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 09f39f83f60..e614d783162 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -1223,4 +1223,5 @@ _aclfromtext = aclfromtext ftok shmat shmctl +shmdt shmget diff --git a/winsup/cygwin/include/cygwin/cygserver.h b/winsup/cygwin/include/cygwin/cygserver.h index bf21e990464..4bf30241be4 100755 --- a/winsup/cygwin/include/cygwin/cygserver.h +++ b/winsup/cygwin/include/cygwin/cygserver.h @@ -87,7 +87,7 @@ class client_request public: client_request (cygserver_request_code id); virtual void send (transport_layer_base *conn); - virtual void serve (transport_layer_base *conn) {}; + virtual void serve (transport_layer_base *conn, class process_cache *cache) {}; virtual operator struct request_header (); cygserver_request_code req_id () {return header.req_id;}; virtual ~client_request(); @@ -98,7 +98,7 @@ class client_request class client_request_get_version : public client_request { public: - virtual void serve (transport_layer_base *conn); + virtual void serve (transport_layer_base *conn, class process_cache *cache); client_request_get_version::client_request_get_version(); struct request_get_version version; }; @@ -106,14 +106,14 @@ class client_request_get_version : public client_request class client_request_shutdown : public client_request { public: - virtual void serve (transport_layer_base *conn); + virtual void serve (transport_layer_base *conn, class process_cache *cache); client_request_shutdown (); }; class client_request_attach_tty : public client_request { public: - virtual void serve (transport_layer_base *conn); + virtual void serve (transport_layer_base *conn, class process_cache *cache); client_request_attach_tty (); client_request_attach_tty (DWORD npid, DWORD nmaster_pid, HANDLE nfrom_master, HANDLE nto_master); HANDLE from_master () {return req.from_master;}; diff --git a/winsup/cygwin/include/cygwin/cygserver_process.h b/winsup/cygwin/include/cygwin/cygserver_process.h new file mode 100755 index 00000000000..e761af3e29f --- /dev/null +++ b/winsup/cygwin/include/cygwin/cygserver_process.h @@ -0,0 +1,43 @@ +/* cygserver_process.h + + Copyright 2001 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 _CYGSERVER_PROCESS_ +#define _CYGSERVER_PROCESS_ + +class process +{ + public: + HANDLE handle (); + long winpid; + process (long); + private: + HANDLE thehandle; +}; + +class process_entry +{ + public: + class process_entry *next; + class process process; + process_entry (long); +}; + +class process_cache +{ + public: + process_cache (); + class process *process (long); + private: + class process_entry *head; +}; + +#endif /* _CYGSERVER_PROCESS_ */ diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc index 840c0f23ac7..2caad7376f5 100644 --- a/winsup/cygwin/shm.cc +++ b/winsup/cygwin/shm.cc @@ -111,7 +111,8 @@ fixup_shms_after_fork () if (!newshmds) { /* don't worry about handle cleanup, we're dying! */ - system_printf("failed to reattach to shm control file view %x\n",tempnode); + system_printf ("failed to reattach to shm control file view %x\n", + tempnode); return 1; } tempnode->shmds = (class shmid_ds *) newshmds; @@ -126,7 +127,8 @@ fixup_shms_after_fork () if (newdata != attachnode->data) { /* don't worry about handle cleanup, we're dying! */ - system_printf("failed to reattach to mapped file view %x\n",attachnode->data); + system_printf ("failed to reattach to mapped file view %x\n", + attachnode->data); return 1; } attachnode = attachnode->next; @@ -142,14 +144,12 @@ fixup_shms_after_fork () */ /* FIXME: after fork, every memory area needs to have the attach count - * incremented and the mappings potentially reestablished, perhaps allowing - * inherit will work?!? + * incremented. This should be done in the server? */ -/* FIXME: are inherited mapped IPC_PRIVATE id's shared between process's - * YES from linux. +/* FIXME: tell the daemon when we attach, so at process close it can clean up + * the attach count */ - extern "C" void * shmat (int shmid, const void *shmaddr, int shmflg) { @@ -221,12 +221,24 @@ shmat (int shmid, const void *shmaddr, int shmflg) attachnode->data = rv; attachnode->shmflg = shmflg; attachnode->next = - (_shmattach *) InterlockedExchangePointer (&tempnode->attachhead, attachnode); + (_shmattach *) InterlockedExchangePointer (&tempnode->attachhead, + attachnode); return rv; } +/* FIXME: tell the daemon when we detach so it doesn't cleanup incorrectly. + */ +extern "C" int +shmdt (const void *shmaddr) +{ + /* this should be "rare" so a hefty search is ok. If this is common, then we + * should alter the data structs to allow more optimisation + */ + +} + //FIXME: who is allowed to perform STAT? extern "C" int shmctl (int shmid, int cmd, struct shmid_ds *buf) @@ -235,46 +247,46 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf) while (tempnode && tempnode->shm_id != shmid) tempnode = tempnode->next; if (!tempnode) - { - /* couldn't find a currently open shm control area for the key - probably because - * shmget hasn't been called. - * Allocate a new control block - this has to be handled by the daemon */ - client_request_shm_get *req = - new client_request_shm_get (shmid, GetCurrentProcessId ()); - - int rc; - if ((rc = cygserver_request (req))) - { - delete req; - set_errno (ENOSYS); /* daemon communication failed */ - return -1; - } + { + /* couldn't find a currently open shm control area for the key - probably because + * shmget hasn't been called. + * Allocate a new control block - this has to be handled by the daemon */ + client_request_shm_get *req = + new client_request_shm_get (shmid, GetCurrentProcessId ()); - if (req->header.error_code) /* shm_get failed in the daemon */ - { - set_errno (req->header.error_code); - delete req; - return -1; - } + int rc; + if ((rc = cygserver_request (req))) + { + delete req; + set_errno (ENOSYS); /* daemon communication failed */ + return -1; + } + + if (req->header.error_code) /* shm_get failed in the daemon */ + { + set_errno (req->header.error_code); + delete req; + return -1; + } + + /* we've got the id, now we open the memory area ourselves. + * This tests security automagically + * FIXME: make this a method of shmnode ? + */ + tempnode = + build_inprocess_shmds (req->parameters.out.filemap, + req->parameters.out.attachmap, + req->parameters.out.key, + req->parameters.out.shm_id); + delete req; + if (!tempnode) + return -1; + } - /* we've got the id, now we open the memory area ourselves. - * This tests security automagically - * FIXME: make this a method of shmnode ? - */ - tempnode = - build_inprocess_shmds (req->parameters.out.filemap, - req->parameters.out.attachmap, - req->parameters.out.key, - req->parameters.out.shm_id); - delete req; - if (!tempnode) - return -1; - } - switch (cmd) { case IPC_STAT: - buf->shm_perm = tempnode->shmds->shm_perm; + buf->shm_perm = tempnode->shmds->shm_perm; buf->shm_segsz = tempnode->shmds->shm_segsz; buf->shm_lpid = tempnode->shmds->shm_lpid; buf->shm_cpid = tempnode->shmds->shm_cpid; @@ -285,40 +297,44 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf) break; case IPC_RMID: { - /* TODO: check permissions. Or possibly, the daemon gets to be the only - * one with write access to the memory area? - */ - if (tempnode->shmds->shm_nattch) - system_printf ("call to shmctl with cmd= IPC_RMID when memory area still has" - " attachees\n"); - /* how does this work? - * we mark the ds area as "deleted", and the at and get calls all fail from now on - * on, when nattch becomes 0, the mapped data area is destroyed. - * and each process, as they touch this area detaches. eventually only the - * daemon has an attach. The daemon gets asked to detach immediately. - */ + /* TODO: check permissions. Or possibly, the daemon gets to be the only + * one with write access to the memory area? + */ + if (tempnode->shmds->shm_nattch) + system_printf + ("call to shmctl with cmd= IPC_RMID when memory area still has" + " attachees\n"); + /* how does this work? + * we mark the ds area as "deleted", and the at and get calls all fail from now on + * on, when nattch becomes 0, the mapped data area is destroyed. + * and each process, as they touch this area detaches. eventually only the + * daemon has an attach. The daemon gets asked to detach immediately. + */ #if 0 - client_request_shm_get *req = +//waiting for the daemon to handle terminating process's + client_request_shm_get *req = new client_request_shm_get (SHM_DEL, shmid, GetCurrentProcessId ()); - int rc; - if ((rc = cygserver_request (req))) - { - delete req; - set_errno (ENOSYS); /* daemon communication failed */ - return -1; - } + int rc; + if ((rc = cygserver_request (req))) + { + delete req; + set_errno (ENOSYS); /* daemon communication failed */ + return -1; + } + + if (req->header.error_code) /* shm_del failed in the daemon */ + { + set_errno (req->header.error_code); + delete req; + return -1; + } + + /* the daemon has deleted it's references */ + /* now for us */ + +#endif - if (req->header.error_code) /* shm_del failed in the daemon */ - { - set_errno (req->header.error_code); - delete req; - return -1; } - - /* the daemon has deleted it's references */ - /* now for us */ -#endif -} break; case IPC_SET: default: @@ -333,10 +349,6 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf) * appropriately */ -/* Test result from openbsd: shm ids are persistent cross process if a handle is left - * open. This could lead to resource starvation: we're not copying that behaviour - * unless we have to. (It will involve acygwin1.dll gloal shared list :[ ). - */ /* FIXME: shmid should be a verifyable object */ |