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

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <rbtcollins@hotmail.com>2001-09-30 17:56:37 +0400
committerRobert Collins <rbtcollins@hotmail.com>2001-09-30 17:56:37 +0400
commitca3e514a1e4f8aa39d208b3d00434e801539f36c (patch)
tree028d7d5be393da1fd6d18d7501ad7e751f10a58b /winsup/cygwin
parentc200af5ddf37bd5c36f036bd89c824e605690234 (diff)
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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog40
-rw-r--r--winsup/cygwin/Makefile.in2
-rwxr-xr-xwinsup/cygwin/cygserver.cc190
-rwxr-xr-xwinsup/cygwin/cygserver_client.cc6
-rwxr-xr-xwinsup/cygwin/cygserver_process.cc72
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc9
-rw-r--r--winsup/cygwin/cygwin.din1
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver.h8
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver_process.h43
-rw-r--r--winsup/cygwin/shm.cc166
10 files changed, 414 insertions, 123 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 828dffd9e..bc5efb631 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 6ab06144e..dc3aa8f30 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 8f30d90dd..083df06af 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, &params->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 266687e26..ef9b87067 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 000000000..8ec1c03e3
--- /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 97246f0e3..e4da727e6 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 09f39f83f..e614d7831 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 bf21e9904..4bf30241b 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 000000000..e761af3e2
--- /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 840c0f23a..2caad7376 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
*/