summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscottc <scottc>2002-07-27 23:01:00 +0000
committerscottc <scottc>2002-07-27 23:01:00 +0000
commitb258b39b6be4131e9dc4ffece74e29b18fbd33c3 (patch)
tree5e1139481390f7ab2ae60954a94acd7f015ffc46
parent9860fb12e3aa07578048dda139127d805dee3e08 (diff)
downloadgdb-b258b39b6be4131e9dc4ffece74e29b18fbd33c3.tar.gz
* include/cygwin/cygserver_process.h
(cleanup_routine::_key): New field. (cleanup_routine::cleanup_routine): Initialise new field with new argument. (cleanup_routine::operator==): New method. (cleanup_routine::cleanup): Make argument non-const. (process::is_active): New method. (process::remove): Ditto. (process::check_exit_code): Rename method. * cygserver_process.cc (process::add): Reorganize code. (process::remove): New method. (process::check_exit_code): Rename method. (process::cleanup): Use new `process::is_active' method. (process_cache::process): Ditto. (process_cache::sync_wait_array): Ditto. (process_cache::check_and_remove_process): Ditto. * cygserver_shm.cc (server_shmmgr): Make `cleanup_t' a friend. (segment_t::detach): Make argument non-const. Remove cleanup object from client if appropriate. (cleanup_t::_segptr): Remove field. (cleanup_t::cleanup_t): Initialise parent explicitly. Remove field. (cleanup_t::segptr): New method. (cleanup_t::cleanup): Add error checking and reporting. (server_shmmgr::shmdt): Make argument non-const. (server_shmmgr::find): New method.
-rw-r--r--winsup/cygwin/ChangeLog29
-rwxr-xr-xwinsup/cygwin/cygserver_process.cc68
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc68
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver_process.h21
4 files changed, 152 insertions, 34 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d046421b1be..9ae7afc6d0a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,34 @@
2002-07-27 Conrad Scott <conrad.scott@dsl.pipex.com>
+ * include/cygwin/cygserver_process.h
+ (cleanup_routine::_key): New field.
+ (cleanup_routine::cleanup_routine): Initialise new field with new
+ argument.
+ (cleanup_routine::operator==): New method.
+ (cleanup_routine::cleanup): Make argument non-const.
+ (process::is_active): New method.
+ (process::remove): Ditto.
+ (process::check_exit_code): Rename method.
+ * cygserver_process.cc (process::add): Reorganize code.
+ (process::remove): New method.
+ (process::check_exit_code): Rename method.
+ (process::cleanup): Use new `process::is_active' method.
+ (process_cache::process): Ditto.
+ (process_cache::sync_wait_array): Ditto.
+ (process_cache::check_and_remove_process): Ditto.
+ * cygserver_shm.cc (server_shmmgr): Make `cleanup_t' a friend.
+ (segment_t::detach): Make argument non-const. Remove cleanup
+ object from client if appropriate.
+ (cleanup_t::_segptr): Remove field.
+ (cleanup_t::cleanup_t): Initialise parent explicitly. Remove
+ field.
+ (cleanup_t::segptr): New method.
+ (cleanup_t::cleanup): Add error checking and reporting.
+ (server_shmmgr::shmdt): Make argument non-const.
+ (server_shmmgr::find): New method.
+
+2002-07-27 Conrad Scott <conrad.scott@dsl.pipex.com>
+
* cygserver.cc (client_request_shutdown::client_request_shutdown):
Comment out verbose tracing statement.
* cygserver_client.cc
diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc
index 679319f0c5c..99eb35acabb 100755
--- a/winsup/cygwin/cygserver_process.cc
+++ b/winsup/cygwin/cygserver_process.cc
@@ -85,7 +85,7 @@ process::~process ()
* client request.
*/
DWORD
-process::exit_code ()
+process::check_exit_code ()
{
if (_hProcess && _hProcess != INVALID_HANDLE_VALUE
&& _exit_status == STILL_ACTIVE
@@ -99,26 +99,56 @@ process::exit_code ()
}
bool
-process::add (cleanup_routine *const new_cleanup)
+process::add (cleanup_routine *const entry)
{
- assert (new_cleanup);
+ assert (entry);
- if (_cleaning_up)
- return false;
+ bool res = 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)
+
+ if (!_cleaning_up)
{
- LeaveCriticalSection (&_access);
- return false;
+ entry->_next = _routines_head;
+ _routines_head = entry;
+ res = true;
}
- new_cleanup->_next = _routines_head;
- _routines_head = new_cleanup;
+
+ 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 (cleanup_routine, ptr);
+ res = true;
+ break;
+ }
+ }
+ }
+
LeaveCriticalSection (&_access);
- return true;
+ return res;
}
/* This is single threaded. It's called after the process is removed
@@ -129,7 +159,7 @@ void
process::cleanup ()
{
EnterCriticalSection (&_access);
- assert (_exit_status != STILL_ACTIVE);
+ assert (!is_active ());
assert (!_cleaning_up);
InterlockedExchange (&_cleaning_up, true);
cleanup_routine *entry = _routines_head;
@@ -222,7 +252,7 @@ process_cache::process (const pid_t cygpid, const DWORD winpid)
}
entry = safe_new (class process, cygpid, winpid);
- if (entry->_exit_status != STILL_ACTIVE)
+ if (!entry->is_active ())
{
LeaveCriticalSection (&_cache_write_access);
safe_delete (process, entry);
@@ -316,7 +346,7 @@ process_cache::sync_wait_array (const HANDLE interrupt_event)
for (class process *ptr = _processes_head; ptr; ptr = ptr->_next)
{
assert (ptr->_hProcess && ptr->_hProcess != INVALID_HANDLE_VALUE);
- assert (ptr->_exit_status == STILL_ACTIVE);
+ assert (ptr->is_active ());
_wait_array[index] = ptr->handle ();
_process_array[index++] = ptr;
@@ -353,7 +383,7 @@ process_cache::check_and_remove_process (const size_t index)
assert (process);
assert (process->handle () == _wait_array[index]);
- if (process->exit_code () == STILL_ACTIVE)
+ if (process->check_exit_code () == STILL_ACTIVE)
return;
debug_printf ("process %d(%lu) has left the building ($? = %lu)",
diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc
index 77a7baa36b1..3d0123e1ead 100755
--- a/winsup/cygwin/cygserver_shm.cc
+++ b/winsup/cygwin/cygserver_shm.cc
@@ -79,6 +79,9 @@ details. */
class server_shmmgr
{
+ class cleanup_t;
+ friend class cleanup_t;
+
private:
class attach_t
{
@@ -129,7 +132,7 @@ private:
}
int attach (class process *, HANDLE & hFileMap);
- int detach (const class process *);
+ int detach (class process *);
private:
static long _sequence;
@@ -145,20 +148,27 @@ private:
{
public:
cleanup_t (segment_t *const segptr)
- : _segptr (segptr)
+ : cleanup_routine (segptr)
{
- assert (_segptr);
+ assert (key ());
}
- virtual void cleanup (const class process *const client)
+ segment_t *segptr () { return static_cast<segment_t *>(key ()); }
+
+ virtual void cleanup (class process *const client)
{
- assert (_segptr);
+ assert (segptr ());
- shmmgr.shmdt (_segptr->_shmid, client);
- }
+ if (!shmmgr.find (segptr ()))
+ debug_printf ("process cleanup called for non-existent segment");
+ else
+ {
+ const int res = shmmgr.shmdt (segptr ()->_shmid, client);
- private:
- segment_t *const _segptr;
+ if (res != 0)
+ debug_printf ("process cleanup failed: %s", strerror (-res));
+ }
+ }
};
public:
@@ -170,7 +180,7 @@ public:
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, const 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 *);
@@ -198,6 +208,8 @@ private:
segment_t *find_by_key (key_t);
segment_t *find (int intid, segment_t **previous = NULL);
+ const segment_t *find (const segment_t *) const;
+
int new_segment (key_t, size_t, int shmflg, pid_t, uid_t, gid_t);
segment_t *new_segment (key_t, size_t, HANDLE);
@@ -316,7 +328,7 @@ server_shmmgr::segment_t::attach (class process *const client,
*---------------------------------------------------------------------------*/
int
-server_shmmgr::segment_t::detach (const class process *const client)
+server_shmmgr::segment_t::detach (class process *const client)
{
attach_t *previous = NULL;
attach_t *const attptr = find (client, &previous);
@@ -324,6 +336,17 @@ server_shmmgr::segment_t::detach (const class process *const client)
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)
@@ -540,7 +563,7 @@ server_shmmgr::shmctl (int & out_shmid,
*---------------------------------------------------------------------------*/
int
-server_shmmgr::shmdt (const int shmid, const class process *const client)
+server_shmmgr::shmdt (const int shmid, class process *const client)
{
syscall_printf ("shmdt (shmid = %d) for %d(%lu)",
shmid, client->cygpid (), client->winpid ());
@@ -714,6 +737,27 @@ server_shmmgr::find (const int intid, segment_t **previous)
return NULL;
}
+
+/*---------------------------------------------------------------------------*
+ * server_shmmgr::find ()
+ *
+ * Used to check that a segptr is still valid. Since it may just be a
+ * random blob of memory, the routine doesn't try to access any of the
+ * "object's" fields.
+ *---------------------------------------------------------------------------*/
+
+const server_shmmgr::segment_t *
+server_shmmgr::find (const segment_t *segptr) const
+{
+ assert (segptr);
+
+ for (segment_t *ptr = _segments_head; ptr; ptr = ptr->_next)
+ if (ptr == segptr)
+ return segptr;
+
+ return NULL;
+}
+
/*---------------------------------------------------------------------------*
* server_shmmgr::new_segment ()
*---------------------------------------------------------------------------*/
diff --git a/winsup/cygwin/include/cygwin/cygserver_process.h b/winsup/cygwin/include/cygwin/cygserver_process.h
index c3c2fa657e5..0706d501e11 100755
--- a/winsup/cygwin/include/cygwin/cygserver_process.h
+++ b/winsup/cygwin/include/cygwin/cygserver_process.h
@@ -41,13 +41,25 @@ class cleanup_routine
friend class process;
public:
- cleanup_routine () : _next (NULL) {}
+ cleanup_routine (void *const key)
+ : _key (key),
+ _next (NULL)
+ {}
+
virtual ~cleanup_routine ();
+ bool operator== (const cleanup_routine &rhs) const
+ {
+ return _key == rhs._key;
+ }
+
+ void *key () { return _key; }
+
/* MUST BE SYNCHRONOUS */
- virtual void cleanup (const class process *) = 0;
+ virtual void cleanup (class process *) = 0;
private:
+ void *const _key;
cleanup_routine *_next;
};
@@ -66,10 +78,13 @@ public:
DWORD winpid () const { return _winpid; }
HANDLE handle () const { return _hProcess; }
+ bool is_active () const { return _exit_status == STILL_ACTIVE; }
+
void hold () { EnterCriticalSection (&_access); }
void release () { LeaveCriticalSection (&_access); }
bool add (cleanup_routine *);
+ bool remove (const cleanup_routine *);
private:
const pid_t _cygpid;
@@ -82,7 +97,7 @@ private:
CRITICAL_SECTION _access;
class process *_next;
- DWORD exit_code ();
+ DWORD check_exit_code ();
void cleanup ();
};