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-10-08 01:58:21 +0400
committerRobert Collins <rbtcollins@hotmail.com>2001-10-08 01:58:21 +0400
commit10caff1aadd69ebe7fbfba162dd23f6b2dc8b5a4 (patch)
treede0de67f94eae69042d5699059c3824df0bd0e9f /winsup/cygwin
parent02baf7ff76fe2853ff0e94dbea52164d60d67acf (diff)
Mon Oct 8 7:41:00 2001 Robert Collins <rbtcollins@hotmail.com>
* cygserver.cc (server_request::process): Rename client_request_shm_get to client_request_shm. * cygserver_process.cc (process_cache::add): Rename to add_task. Use process_cleanup instead of process_request. (process_cache::remove_process): New method. (process::process): Initialize new members. (process::~process): New member. (process::cleanup): New method. (process::add_cleanup_routine): New method. (process_request::process): Rename to process_cleanup. Call the process object's cleanup method and then delete it. (process_process_param::request_loop): Remove the signalling process. * cygserver_shm.cc: Globally rename client_request_shm_get to client_request_shm. (client_request_shm_get::serve): Handle attach request counting. * cygserver_shm.h: Globally rename client_request_shm_get to client_request_shm. (class shm_cleanup): New class. * shm.cc: Globally rename client_request_shm_get to client_request_shm. (client_request_shm::client_request_shm): New constructor for attach requests. (shmat): Use it. * include/cygwin/cygserver_process.h (class process_request): Rename to process_cleanup. (class cleanup_routine): New class. (class process): New members and methods to allow calling back when the process terminates.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog27
-rwxr-xr-xwinsup/cygwin/cygserver.cc2
-rwxr-xr-xwinsup/cygwin/cygserver_process.cc97
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc33
-rw-r--r--winsup/cygwin/cygserver_shm.h18
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver_process.h27
-rw-r--r--winsup/cygwin/shm.cc40
7 files changed, 214 insertions, 30 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 67ff204a7..59a42075d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,30 @@
+Mon Oct 8 7:41:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * cygserver.cc (server_request::process): Rename client_request_shm_get to
+ client_request_shm.
+ * cygserver_process.cc (process_cache::add): Rename to add_task.
+ Use process_cleanup instead of process_request.
+ (process_cache::remove_process): New method.
+ (process::process): Initialize new members.
+ (process::~process): New member.
+ (process::cleanup): New method.
+ (process::add_cleanup_routine): New method.
+ (process_request::process): Rename to process_cleanup.
+ Call the process object's cleanup method and then delete it.
+ (process_process_param::request_loop): Remove the signalling process.
+ * cygserver_shm.cc: Globally rename client_request_shm_get to client_request_shm.
+ (client_request_shm_get::serve): Handle attach request counting.
+ * cygserver_shm.h: Globally rename client_request_shm_get to client_request_shm.
+ (class shm_cleanup): New class.
+ * shm.cc: Globally rename client_request_shm_get to client_request_shm.
+ (client_request_shm::client_request_shm): New constructor for attach requests.
+ (shmat): Use it.
+ * include/cygwin/cygserver_process.h (class process_request): Rename to
+ process_cleanup.
+ (class cleanup_routine): New class.
+ (class process): New members and methods to allow calling back when the process
+ terminates.
+
Thu Oct 4 14:12:00 2001 Robert Collins <rbtcollins@hotmail.com>
* cygserver.cc (request_loop): Make static.
diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc
index b0b815beb..24a90dc20 100755
--- a/winsup/cygwin/cygserver.cc
+++ b/winsup/cygwin/cygserver.cc
@@ -370,7 +370,7 @@ server_request::process ()
case CYGSERVER_REQUEST_SHUTDOWN:
req = new client_request_shutdown (); break;
case CYGSERVER_REQUEST_SHM_GET:
- req = new client_request_shm_get (); break;
+ req = new client_request_shm (); break;
default:
req = new client_request (CYGSERVER_REQUEST_INVALID, 0);
req->header.error_code = ENOSYS;
diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc
index fe5b5b80b..a5173afd3 100755
--- a/winsup/cygwin/cygserver_process.cc
+++ b/winsup/cygwin/cygserver_process.cc
@@ -95,18 +95,50 @@ process_cache::process_requests ()
}
void
-process_cache::add ()
+process_cache::add_task (class process * theprocess)
{
/* safe to not "Try" because workers don't hog this, they wait on the event
*/
/* every derived ::add must enter the section! */
EnterCriticalSection (&queuelock);
- queue_request *listrequest = new process_request;
+ queue_request *listrequest = new process_cleanup (theprocess);
threaded_queue::add (listrequest);
LeaveCriticalSection (&queuelock);
}
-
+/* NOT fully MT SAFE: must be called by only one thread in a program */
+void
+process_cache::remove_process (class process *theprocess)
+{
+ class process *entry = head;
+ /* unlink */
+ EnterCriticalSection (&cache_write_access);
+ if (entry == theprocess)
+ {
+ entry = (class process *) InterlockedExchangePointer (&head, theprocess->next);
+ if (entry != theprocess)
+ {
+ printf ("Bug encountered, process cache corrupted\n");
+ exit (1);
+ }
+ }
+ else
+ {
+ while (entry->next && entry->next != theprocess)
+ entry = entry->next;
+ class process *temp = (class process *) InterlockedExchangePointer (&entry->next, theprocess->next);
+ if (temp != theprocess)
+ {
+ printf ("Bug encountered, process cache corrupted\n");
+ exit (1);
+ }
+ }
+ LeaveCriticalSection (&cache_write_access);
+ /* Process any cleanup tasks */
+ add_task (theprocess);
+}
+
+
/* copy <= max_copy HANDLEs to dest[], starting at an offset into _our list_ of
* begin_at. (Ie begin_at = 5, the first copied handle is still written to dest[0]
* NOTE: Thread safe, but not thread guaranteed - a newly added process may be missed.
@@ -148,6 +180,7 @@ process_cache::handle_snapshot (HANDLE * hdest, class process ** edest,
}
/* process's */
+/* global process crit section */
static CRITICAL_SECTION process_access;
static pthread_once_t process_init;
@@ -159,7 +192,7 @@ do_process_init (void)
}
process::process (long pid):
-winpid (pid), next (NULL), _exit_status (STILL_ACTIVE)
+winpid (pid), next (NULL), cleaning_up (0), head (NULL), _exit_status (STILL_ACTIVE)
{
pthread_once (&process_init, do_process_init);
EnterCriticalSection (&process_access);
@@ -170,9 +203,15 @@ winpid (pid), next (NULL), _exit_status (STILL_ACTIVE)
thehandle = INVALID_HANDLE_VALUE;
}
debug_printf ("Got handle %p for new cache process %ld\n", thehandle, pid);
+ InitializeCriticalSection (&access);
LeaveCriticalSection (&process_access);
}
+process::~process ()
+{
+ DeleteCriticalSection (&access);
+}
+
HANDLE
process::handle ()
{
@@ -216,11 +255,53 @@ DWORD process::exit_code ()
return _exit_status;
}
-/* process_request */
+/* 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 ()
+{
+ /* Serialize this */
+ EnterCriticalSection (&access);
+ InterlockedIncrement (&(long)cleaning_up);
+ class cleanup_routine *entry = head;
+ while (entry)
+ {
+ class cleanup_routine *temp;
+ entry->cleanup (winpid);
+ temp = entry->next;
+ delete entry;
+ entry = temp;
+ }
+ LeaveCriticalSection (&access);
+}
+
+bool
+process::add_cleanup_routine (class cleanup_routine *new_cleanup)
+{
+ if (cleaning_up)
+ return false;
+ EnterCriticalSection (&access);
+ /* check that we didn't block with ::cleanup ()
+ * This rigmarole is to get around win9x's glaring missing TryEnterCriticalSection call
+ * which would be a whole lot easier
+ */
+ if (cleaning_up)
+ {
+ LeaveCriticalSection (&access);
+ return false;
+ }
+ new_cleanup->next = head;
+ head = new_cleanup;
+ LeaveCriticalSection (&access);
+ return true;
+}
+
+/* process_cleanup */
void
-process_request::process ()
+process_cleanup::process ()
{
- printf ("processing...\n");
+ theprocess->cleanup ();
+ delete theprocess;
}
/* process_process_param */
@@ -290,7 +371,7 @@ process_process_param::request_loop ()
debug_printf ("Process %ld has left the building\n",
Entries[objindex]->winpid);
/* fire off the termination routines */
-
+ cache->remove_process (Entries[objindex]);
}
else if (objindex >= 0 && objindex < 2)
{
diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc
index 134f810e6..c29938bb9 100755
--- a/winsup/cygwin/cygserver_shm.cc
+++ b/winsup/cygwin/cygserver_shm.cc
@@ -44,9 +44,9 @@
#include <sys/shm.h>
#endif
//#include "perprocess.h"
-#include "cygserver_shm.h"
#include <threaded_queue.h>
#include <cygwin/cygserver_process.h>
+#include "cygserver_shm.h"
// FIXME IS THIS CORRECT
/* Implementation notes: We use two shared memory regions per key:
@@ -70,7 +70,7 @@ getsystemallocgranularity ()
}
-client_request_shm_get::client_request_shm_get ():client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
+client_request_shm::client_request_shm ():client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
{
buffer = (char *) &parameters;
}
@@ -152,7 +152,7 @@ static long new_id = 0;
static long new_private_key = 0;
void
-client_request_shm_get::serve (transport_layer_base * conn,
+client_request_shm::serve (transport_layer_base * conn,
process_cache * cache)
{
// DWORD sd_size = 4096;
@@ -208,6 +208,7 @@ client_request_shm_get::serve (transport_layer_base * conn,
char *shmname = NULL, *shmaname = NULL;
char stringbuf[29], stringbuf1[29];
+ /* TODO: make this code block a function! */
if (parameters.in.type == SHM_REATTACH)
{
/* just find and fill out the existing shm_id */
@@ -245,6 +246,32 @@ client_request_shm_get::serve (transport_layer_base * conn,
CloseHandle (token_handle);
return;
}
+
+ /* someone attached */
+ /* someone can send shm_id's they don't have and currently we will increment those
+ * attach counts. If someone wants to fix that, please go ahead.
+ * The problem is that shm_get has nothing to do with the ability to attach. Attach
+ * requires a permission check, which we get the OS to do in MapViewOfFile.
+ */
+ if (parameters.in.type == SHM_ATTACH)
+ {
+ shmnode *tempnode = shm_head;
+ while (tempnode)
+ {
+ if (tempnode->shm_id == parameters.in.shm_id)
+ {
+ InterlockedIncrement (&tempnode->shmds->shm_nattch);
+ header.error_code = 0;
+ CloseHandle (token_handle);
+ return;
+ }
+ tempnode = tempnode->next;
+ }
+ header.error_code = EINVAL;
+ CloseHandle (token_handle);
+ return;
+ }
+
/* it's a original request from the users */
/* FIXME: enter the checking for existing keys mutex. This mutex _must_ be system wide
diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h
index 20d5e5db9..32947f8ec 100644
--- a/winsup/cygwin/cygserver_shm.h
+++ b/winsup/cygwin/cygserver_shm.h
@@ -15,23 +15,33 @@ details. */
#define SHM_CREATE 0
#define SHM_REATTACH 1
+#define SHM_ATTACH 2
+#define SHM_DETACH 3
-class client_request_shm_get : public client_request
+class client_request_shm : public client_request
{
public:
#ifndef __INSIDE_CYGWIN__
virtual void serve (transport_layer_base *conn, process_cache *cache);
#endif
- client_request_shm_get::client_request_shm_get(key_t, size_t, int, char psdbuf[4096], pid_t);
- client_request_shm_get::client_request_shm_get();
- client_request_shm_get::client_request_shm_get(int,pid_t);
+ client_request_shm (key_t, size_t, int, char psdbuf[4096], pid_t);
+ client_request_shm ();
+ client_request_shm (int, int, pid_t);
+ client_request_shm (int, int);
union {
struct {int type; pid_t pid; int shm_id; key_t key; size_t size; int shmflg; char sd_buf[4096];} in;
struct {int shm_id; HANDLE filemap; HANDLE attachmap; key_t key;} out;
} parameters;
};
+#ifndef __INSIDE_CYGWIN__
+class shm_cleanup : cleanup_routine
+{
+public:
+ virtual void cleanup (long winpid);
+};
+#endif
#if 0
class _shmattach {
public:
diff --git a/winsup/cygwin/include/cygwin/cygserver_process.h b/winsup/cygwin/include/cygwin/cygserver_process.h
index 75cae51a7..4a49212b2 100755
--- a/winsup/cygwin/include/cygwin/cygserver_process.h
+++ b/winsup/cygwin/include/cygwin/cygserver_process.h
@@ -15,10 +15,13 @@
/* needs threaded_queue.h */
-class process_request:public queue_request
+class process_cleanup:public queue_request
{
public:
virtual void process ();
+ process_cleanup (class process *nprocess) : theprocess (nprocess) {};
+private:
+ class process * theprocess;
};
class process_process_param:public queue_process_param
@@ -29,15 +32,32 @@ public:
process_process_param ():queue_process_param (true) {};
};
+class cleanup_routine
+{
+public:
+ cleanup_routine () : next (NULL) {};
+ class cleanup_routine * next;
+ /* MUST BE SYNCHRONOUS */
+ virtual void cleanup (long winpid);
+};
+
class process
{
public:
HANDLE handle ();
long winpid;
process (long);
+ ~process ();
DWORD exit_code ();
class process * next;
+ long refcount;
+ bool add_cleanup_routine (class cleanup_routine *);
+ void cleanup ();
private:
+ /* used to prevent races-on-delete */
+ CRITICAL_SECTION access;
+ volatile long cleaning_up;
+ class cleanup_routine *head;
HANDLE thehandle;
DWORD _exit_status;
};
@@ -48,12 +68,15 @@ public:
process_cache (unsigned int initial_workers);
virtual ~ process_cache ();
class process *process (long);
+ /* remove a process from the cache */
int handle_snapshot (HANDLE *, class process **, ssize_t, int);
+ void remove_process (class process *);
/* threaded_queue methods */
void process_requests ();
HANDLE cache_add_trigger;
+
private:
- virtual void add ();
+ virtual void add_task (class process *);
class process *head;
CRITICAL_SECTION cache_write_access;
};
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
index 268ccbd2b..dbe9bb0e9 100644
--- a/winsup/cygwin/shm.cc
+++ b/winsup/cygwin/shm.cc
@@ -45,16 +45,25 @@ getsystemallocgranularity ()
return buffer_offset;
}
-client_request_shm_get::client_request_shm_get (int nshm_id, pid_t npid):
+client_request_shm::client_request_shm (int ntype, int nshm_id):
client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
{
buffer = (char *) &parameters;
parameters.in.shm_id = nshm_id;
parameters.in.type = SHM_REATTACH;
+ parameters.in.pid = GetCurrentProcessId ();
+}
+
+client_request_shm::client_request_shm (int ntype, int nshm_id, pid_t npid):
+client_request (CYGSERVER_REQUEST_SHM_GET, sizeof (parameters))
+{
+ buffer = (char *) &parameters;
+ parameters.in.shm_id = nshm_id;
+ parameters.in.type = ntype;
parameters.in.pid = npid;
}
-client_request_shm_get::client_request_shm_get (key_t nkey, size_t nsize,
+client_request_shm::client_request_shm (key_t nkey, size_t nsize,
int nshmflg,
char psdbuf[4096],
pid_t npid):
@@ -187,8 +196,8 @@ shmat (int shmid, const void *shmaddr, int shmflg)
/* 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 ());
+ client_request_shm *req =
+ new client_request_shm (SHM_REATTACH, shmid, GetCurrentProcessId ());
int rc;
if ((rc = cygserver_request (req)))
@@ -239,10 +248,17 @@ shmat (int shmid, const void *shmaddr, int shmflg)
set_errno (EACCES);
return (void *) -1;
}
+ /* tell the daemon we have attached */
+ client_request_shm *req =
+ new client_request_shm (SHM_ATTACH, shmid);
+ int rc;
+ if ((rc = cygserver_request (req)))
+ {
+ debug_printf ("failed to tell deaemon that we have attached\n");
+ }
+ delete req;
- InterlockedIncrement (&shm->shm_nattch);
_shmattach *attachnode = new _shmattach;
-
attachnode->data = rv;
attachnode->shmflg = shmflg;
attachnode->next =
@@ -276,8 +292,8 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
/* 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 ());
+ client_request_shm *req =
+ new client_request_shm (SHM_REATTACH, shmid, GetCurrentProcessId ());
int rc;
if ((rc = cygserver_request (req)))
@@ -337,8 +353,8 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
*/
#if 0
//waiting for the daemon to handle terminating process's
- client_request_shm_get *req =
- new client_request_shm_get (SHM_DEL, shmid, GetCurrentProcessId ());
+ client_request_shm *req =
+ new client_request_shm (SHM_DEL, shmid, GetCurrentProcessId ());
int rc;
if ((rc = cygserver_request (req)))
{
@@ -428,8 +444,8 @@ shmget (key_t key, size_t size, int shmflg)
}
/* couldn't find a currently open shm control area for the key.
* Allocate a new control block - this has to be handled by the daemon */
- client_request_shm_get *req =
- new client_request_shm_get (key, size, shmflg, sd_buf,
+ client_request_shm *req =
+ new client_request_shm (key, size, shmflg, sd_buf,
GetCurrentProcessId ());
int rc;