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:
authorConrad Scott <conrad.scott@dsl.pipex.com>2002-07-11 17:58:14 +0400
committerConrad Scott <conrad.scott@dsl.pipex.com>2002-07-11 17:58:14 +0400
commitf039cc3a2544c08cd8fd0fef06eb727df17604a4 (patch)
tree0e56ca42f686c47e5417bcf0f1950ec012b44010
parent918edb5bbd86472f4b6b6e616bc288524307b616 (diff)
* cygserver_shm.cc: Automatically detach processes from any
segments they are attached to at exit. (class server_shmmgr::attach_t): New class. (server_shmmgr::segment_t::IS_DELETED): Rename and make private. (server_shmmgr::segment_t::_sequence): Make private. (server_shmmgr::segment_t::_flg): Ditto. (server_shmmgr::segment_t::_hFileMap): Ditto. (server_shmmgr::segment_t::_attach_head): New private field. (server_shmmgr::segment_t::segment_t): Initialise new fields. Make non-inline. (server_shmmgr::segment_t::~segment_t): New method. (server_shmmgr::segment_t::is_deleted): Ditto. (server_shmmgr::segment_t::is_pending_delete): Ditto. (server_shmmgr::segment_t::mark_deleted): Ditto. (server_shmmgr::segment_t::attach): Ditto. (server_shmmgr::segment_t::detach): Ditto. (server_shmmgr::segment_t::find): Ditto. (class server_shmmgr::cleanup_t): New class. (server_shmmgr::_shm_atts): New private field. (server_shmmgr::shmat): Add a process object argument to replace the removed process_cache, cygpid and winpid arguments. Remove the process_cache manipulations. Move body of code to the segment_t::attach method. Increment _shm_atts when required. Update tracing statements. (server_shmmgr::shmdt): Add a process object argument to replace the removed cygpid argument. Move body of code to the segment_t::detach method. Decrement _shm_atts when required. Update tracing statements. (server_shmmgr::shmget): Use the new segment_t::is_deleted method. (server_shmmgr::server_shmmgr): Initialise the new _shm_atts field. (server_shmmgr::delete_segment): Remove the CloseHandle code, as this is now done in the segment_t destructor. (client_request_shm::serve): Look up the client's process object and pass to the server_shmmgr::shmat and server_shmmgr::shmdt methods rather than passing the cache, winpid and cygpid. * cygserver_process.h: Add a cygpid to the process object to make it more useful and then pass process objects rather than winpids where possible. (cleanup_routine::cleanup): Change argument to be a pointer to a process object. (class process): Re-order fields for no discernible reason. (process::_cygpid): New field. (process::process): Add a cygpid argument. (process::winpid): New method. (process::cygpid): Ditto. (process::add): Make public, as it always should have been. (process_cache::process): Add a cygpid argument. * cygserver_process.cc (process::process): Add a cygpid argument and use it to initialise the `_cygpid' field. Re-order initialisers to match new field order. (process::cleanup): Pass `this' rather than just the winpid to cleanup_routine::cleanup. (process_cache::process): Add a cygpid argument and pass it to the process object constructor. * include/sys/shm.h (shmatt_t): Make unsigned as per SUSv3. (shm_info::shm_atts): New field.
-rw-r--r--winsup/cygwin/ChangeLog60
-rwxr-xr-xwinsup/cygwin/cygserver_process.cc20
-rwxr-xr-xwinsup/cygwin/cygserver_shm.cc367
-rwxr-xr-xwinsup/cygwin/include/cygwin/cygserver_process.h18
-rw-r--r--winsup/cygwin/include/sys/shm.h4
5 files changed, 363 insertions, 106 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6ed4e52d5..c7d973178 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,65 @@
2002-07-11 Conrad Scott <conrad.scott@dsl.pipex.com>
+ * cygserver_shm.cc: Automatically detach processes from any
+ segments they are attached to at exit.
+ (class server_shmmgr::attach_t): New class.
+ (server_shmmgr::segment_t::IS_DELETED): Rename and make private.
+ (server_shmmgr::segment_t::_sequence): Make private.
+ (server_shmmgr::segment_t::_flg): Ditto.
+ (server_shmmgr::segment_t::_hFileMap): Ditto.
+ (server_shmmgr::segment_t::_attach_head): New private field.
+ (server_shmmgr::segment_t::segment_t): Initialise new fields.
+ Make non-inline.
+ (server_shmmgr::segment_t::~segment_t): New method.
+ (server_shmmgr::segment_t::is_deleted): Ditto.
+ (server_shmmgr::segment_t::is_pending_delete): Ditto.
+ (server_shmmgr::segment_t::mark_deleted): Ditto.
+ (server_shmmgr::segment_t::attach): Ditto.
+ (server_shmmgr::segment_t::detach): Ditto.
+ (server_shmmgr::segment_t::find): Ditto.
+ (class server_shmmgr::cleanup_t): New class.
+ (server_shmmgr::_shm_atts): New private field.
+ (server_shmmgr::shmat): Add a process object argument to replace
+ the removed process_cache, cygpid and winpid arguments. Remove
+ the process_cache manipulations. Move body of code to the
+ segment_t::attach method. Increment _shm_atts when required.
+ Update tracing statements.
+ (server_shmmgr::shmdt): Add a process object argument to replace
+ the removed cygpid argument. Move body of code to the
+ segment_t::detach method. Decrement _shm_atts when required.
+ Update tracing statements.
+ (server_shmmgr::shmget): Use the new segment_t::is_deleted method.
+ (server_shmmgr::server_shmmgr): Initialise the new _shm_atts
+ field.
+ (server_shmmgr::delete_segment): Remove the CloseHandle code, as
+ this is now done in the segment_t destructor.
+ (client_request_shm::serve): Look up the client's process object
+ and pass to the server_shmmgr::shmat and server_shmmgr::shmdt
+ methods rather than passing the cache, winpid and cygpid.
+ * cygserver_process.h: Add a cygpid to the process object to make
+ it more useful and then pass process objects rather than winpids
+ where possible.
+ (cleanup_routine::cleanup): Change argument to be a pointer to a
+ process object.
+ (class process): Re-order fields for no discernible reason.
+ (process::_cygpid): New field.
+ (process::process): Add a cygpid argument.
+ (process::winpid): New method.
+ (process::cygpid): Ditto.
+ (process::add): Make public, as it always should have been.
+ (process_cache::process): Add a cygpid argument.
+ * cygserver_process.cc (process::process): Add a cygpid argument
+ and use it to initialise the `_cygpid' field. Re-order
+ initialisers to match new field order.
+ (process::cleanup): Pass `this' rather than just the winpid to
+ cleanup_routine::cleanup.
+ (process_cache::process): Add a cygpid argument and pass it to the
+ process object constructor.
+ * include/sys/shm.h (shmatt_t): Make unsigned as per SUSv3.
+ (shm_info::shm_atts): New field.
+
+2002-07-11 Conrad Scott <conrad.scott@dsl.pipex.com>
+
* cygserver_shm.cc (class server_shmmgr::segment_t): Add `_'
prefix to the names of all fields.
diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc
index 2760dd013..2eb5a5229 100755
--- a/winsup/cygwin/cygserver_process.cc
+++ b/winsup/cygwin/cygserver_process.cc
@@ -48,13 +48,14 @@ cleanup_routine::~cleanup_routine ()
/*****************************************************************************/
-process::process (const DWORD winpid)
- : _winpid (winpid),
- _next (NULL),
+process::process (const pid_t cygpid, const DWORD winpid)
+ : _cygpid (cygpid),
+ _winpid (winpid),
+ _hProcess (NULL),
_cleaning_up (false),
- _routines_head (NULL),
_exit_status (STILL_ACTIVE),
- _hProcess (NULL)
+ _routines_head (NULL),
+ _next (NULL)
{
_hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid);
if (!_hProcess)
@@ -99,6 +100,8 @@ process::exit_code ()
bool
process::add (cleanup_routine *const new_cleanup)
{
+ assert (new_cleanup);
+
if (_cleaning_up)
return false;
EnterCriticalSection (&_access);
@@ -125,6 +128,7 @@ void
process::cleanup ()
{
EnterCriticalSection (&_access);
+ assert (_exit_status != STILL_ACTIVE);
assert (!_cleaning_up);
InterlockedExchange (&_cleaning_up, true);
cleanup_routine *entry = _routines_head;
@@ -135,7 +139,7 @@ process::cleanup ()
{
cleanup_routine *const ptr = entry;
entry = entry->_next;
- ptr->cleanup (_winpid);
+ ptr->cleanup (this);
safe_delete (cleanup_routine, ptr);
}
}
@@ -194,7 +198,7 @@ process_cache::~process_cache ()
* have been deleted once it has been unlocked.
*/
class process *
-process_cache::process (const DWORD winpid)
+process_cache::process (const pid_t cygpid, const DWORD winpid)
{
/* TODO: make this more granular, so a search doesn't involve the
* write lock.
@@ -215,7 +219,7 @@ process_cache::process (const DWORD winpid)
return NULL;
}
- entry = safe_new (class process, winpid);
+ entry = safe_new (class process, cygpid, winpid);
if (entry->_exit_status != STILL_ACTIVE)
{
LeaveCriticalSection (&_cache_write_access);
diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc
index 9c32642e0..27ca6ea7c 100755
--- a/winsup/cygwin/cygserver_shm.cc
+++ b/winsup/cygwin/cygserver_shm.cc
@@ -80,45 +80,96 @@ details. */
class server_shmmgr
{
private:
- class segment_t
+ class attach_t
{
public:
- // Bits for the _flg field.
- enum { REMOVED = 0x01 };
+ class process *const _client;
+ unsigned int _refcnt;
- static long _sequence;
+ 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 (const class process *);
+
+ private:
+ static long _sequence;
+
int _flg;
const HANDLE _hFileMap;
+ attach_t *_attach_head; // A list sorted by winpid;
- segment_t *_next;
+ attach_t *find (const class process *, attach_t **previous = NULL);
+ };
+
+ class cleanup_t : public cleanup_routine
+ {
+ public:
+ cleanup_t (segment_t *const segptr)
+ : _segptr (segptr)
+ {
+ assert (_segptr);
+ }
- segment_t (const key_t key, const int intid, const HANDLE hFileMap)
- : _intid (intid),
- _shmid (ipc_int2ext (_intid, IPC_SHMOP, _sequence)),
- _flg (0),
- _hFileMap (hFileMap),
- _next (NULL)
+ virtual void cleanup (const class process *const client)
{
- assert (0 <= _intid && _intid < SHMMNI);
+ assert (_segptr);
- memset (&_ds, '\0', sizeof (_ds));
- _ds.shm_perm.key = key;
+ shmmgr.shmdt (_segptr->_shmid, client);
}
+
+ private:
+ segment_t *const _segptr;
};
public:
static server_shmmgr & instance ();
int shmat (HANDLE & hFileMap,
- int shmid, int shmflg, pid_t, process_cache *, DWORD winpid);
+ 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 &, pid_t);
- int shmdt (int shmid, pid_t);
+ int shmdt (int shmid, const class process *);
int shmget (int & out_shmid, key_t, size_t, int shmflg, pid_t, uid_t, gid_t);
private:
@@ -132,6 +183,7 @@ private:
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 ();
@@ -156,6 +208,168 @@ private:
/* 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))
+ with_strerr
+ (msg,
+ syscall_printf (("failed to close file map [handle = 0x%x]: %s"),
+ _hFileMap, msg));
+}
+
+/*---------------------------------------------------------------------------*
+ * 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))
+ {
+ with_strerr
+ (msg,
+ syscall_printf (("failed to duplicate handle for client "
+ "[key = 0x%016llx, shmid = %d, handle = 0x%x]:"
+ "%s"),
+ _ds.shm_perm.key, _shmid, _hFileMap,
+ msg));
+
+ 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 (const class process *const client)
+{
+ attach_t *previous = NULL;
+ attach_t *const attptr = find (client, &previous);
+
+ if (!attptr)
+ return -EINVAL;
+
+ 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 (attach_t, 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 ()
*---------------------------------------------------------------------------*/
@@ -176,22 +390,10 @@ server_shmmgr::instance ()
int
server_shmmgr::shmat (HANDLE & hFileMap,
const int shmid, const int shmflg,
- const pid_t cygpid,
- process_cache *const cache, const DWORD winpid)
+ class process *const client)
{
- syscall_printf ("shmat (shmid = %d, shmflg = 0%o) for %d(%lu)",
- shmid, shmflg, cygpid, winpid);
-
- process *const client = cache->process (winpid);
-
- if (!client)
- {
- syscall_printf (("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) "
- "for %d(%lu)"),
- 0, EAGAIN, shmid, shmflg,
- cygpid, winpid);
- return -EAGAIN;
- }
+ syscall_printf ("shmat (shmid = %d, shmflg = 0%o) for %d",
+ shmid, shmflg, client->cygpid ());
int result = 0;
EnterCriticalSection (&_segments_lock);
@@ -200,40 +402,20 @@ server_shmmgr::shmat (HANDLE & hFileMap,
if (!segptr)
result = -EINVAL;
- else if (!DuplicateHandle (GetCurrentProcess (),
- segptr->_hFileMap,
- client->handle (),
- &hFileMap,
- 0,
- FALSE, // bInheritHandle
- DUPLICATE_SAME_ACCESS))
- {
- with_strerr (msg,
- syscall_printf (("failed to duplicate handle for client "
- "[key = 0x%016llx, shmid = %d, handle = 0x%x]:"
- "%s"),
- segptr->_ds.shm_perm.key, segptr->_shmid,
- segptr->_hFileMap, msg));
-
- result = -EACCES; // FIXME
- }
else
- {
- segptr->_ds.shm_lpid = cygpid;
- segptr->_ds.shm_nattch += 1;
- segptr->_ds.shm_atime = time (NULL); // FIXME: sub-second times.
- }
+ result = segptr->attach (client, hFileMap);
- LeaveCriticalSection (&_segments_lock);
+ if (!result)
+ _shm_atts += 1;
- client->release ();
+ LeaveCriticalSection (&_segments_lock);
if (result < 0)
- syscall_printf ("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) for %d(%lu)",
- -result, shmid, shmflg, cygpid, winpid);
+ syscall_printf ("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) for %d",
+ -result, shmid, shmflg, client->cygpid ());
else
- syscall_printf ("0x%x = shmat (shmid = %d, shmflg = 0%o) for %d(%lu)",
- hFileMap, shmid, shmflg, cygpid, winpid);
+ syscall_printf ("0x%x = shmat (shmid = %d, shmflg = 0%o) for %d",
+ hFileMap, shmid, shmflg, client->cygpid ());
return result;
}
@@ -291,12 +473,12 @@ server_shmmgr::shmctl (int & out_shmid,
break;
case IPC_RMID:
- if (segptr->_flg & segment_t::REMOVED)
+ if (segptr->is_deleted ())
result = -EIDRM;
else
{
- segptr->_flg |= segment_t::REMOVED;
- if (!segptr->_ds.shm_nattch)
+ segptr->mark_deleted ();
+ if (segptr->is_pending_delete ())
delete_segment (segptr);
}
break;
@@ -321,6 +503,7 @@ server_shmmgr::shmctl (int & out_shmid,
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:
@@ -351,10 +534,10 @@ server_shmmgr::shmctl (int & out_shmid,
*---------------------------------------------------------------------------*/
int
-server_shmmgr::shmdt (const int shmid, const pid_t cygpid)
+server_shmmgr::shmdt (const int shmid, const class process *const client)
{
syscall_printf ("shmdt (shmid = %d) for %d",
- shmid, cygpid);
+ shmid, client->cygpid ());
int result = 0;
EnterCriticalSection (&_segments_lock);
@@ -364,25 +547,22 @@ server_shmmgr::shmdt (const int shmid, const pid_t cygpid)
if (!segptr)
result = -EINVAL;
else
- {
- assert (segptr->_ds.shm_nattch > 0);
+ result = segptr->detach (client);
- segptr->_ds.shm_lpid = cygpid;
- segptr->_ds.shm_nattch -= 1;
- segptr->_ds.shm_dtime = time (NULL); // FIXME: sub-second times.
+ if (!result)
+ _shm_atts -= 1;
- if (!segptr->_ds.shm_nattch && (segptr->_flg & segment_t::REMOVED))
- delete_segment (segptr);
- }
+ if (segptr->is_pending_delete ())
+ delete_segment (segptr);
LeaveCriticalSection (&_segments_lock);
if (result < 0)
syscall_printf ("-1 [%d] = shmdt (shmid = %d) for %d",
- -result, shmid, cygpid);
+ -result, shmid, client->cygpid ());
else
syscall_printf ("%d = shmdt (shmid = %d) for %d",
- result, shmid, cygpid);
+ result, shmid, client->cygpid ());
return result;
}
@@ -414,7 +594,7 @@ server_shmmgr::shmget (int & out_shmid,
result = new_segment (key, size, shmflg, cygpid, uid, gid);
else
result = -ENOENT;
- else if (segptr->_flg & segment_t::REMOVED)
+ else if (segptr->is_deleted ())
result = -EIDRM;
else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL))
result = -EEXIST;
@@ -462,6 +642,8 @@ server_shmmgr::initialise_instance ()
assert (!_instance);
_instance = safe_new0 (server_shmmgr);
+
+ assert (_instance);
}
/*---------------------------------------------------------------------------*
@@ -472,6 +654,7 @@ server_shmmgr::server_shmmgr ()
: _segments_head (NULL),
_shm_ids (0),
_shm_tot (0),
+ _shm_atts (0),
_intid_max (0)
{
InitializeCriticalSection (&_segments_lock);
@@ -543,10 +726,10 @@ server_shmmgr::new_segment (const key_t key,
if (!hFileMap)
{
- with_strerr (msg,
- syscall_printf (("failed to create file mapping "
- "[size = %lu]: %s"),
- size, msg));
+ with_strerr
+ (msg,
+ syscall_printf (("failed to create file mapping [size = %lu]: %s"),
+ size, msg));
return -ENOMEM; // FIXME
}
@@ -580,6 +763,7 @@ 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;
@@ -632,8 +816,7 @@ void
server_shmmgr::delete_segment (segment_t *const segptr)
{
assert (segptr);
- assert (!segptr->_ds.shm_nattch);
- assert (segptr->_flg & segment_t::REMOVED);
+ assert (segptr->is_pending_delete ());
segment_t *previous = NULL;
@@ -647,12 +830,6 @@ server_shmmgr::delete_segment (segment_t *const segptr)
else
_segments_head = segptr->_next;
- if (!CloseHandle (segptr->_hFileMap))
- with_strerr (msg,
- syscall_printf (("failed to close file map "
- "[handle = 0x%x]: %s"),
- segptr->_hFileMap, msg));
-
assert (_shm_ids > 0);
_shm_ids -= 1;
_shm_tot -= segptr->_ds.shm_segsz;
@@ -695,6 +872,16 @@ client_request_shm::serve (transport_layer_base *const conn,
// 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)
@@ -709,12 +896,11 @@ client_request_shm::serve (transport_layer_base *const conn,
case SHMOP_shmat:
result = shmmgr.shmat (_parameters.out.hFileMap,
_parameters.in.shmid, _parameters.in.shmflg,
- _parameters.in.cygpid,
- cache, _parameters.in.winpid);
+ client);
break;
case SHMOP_shmdt:
- result = shmmgr.shmdt (_parameters.in.shmid, _parameters.in.cygpid);
+ result = shmmgr.shmdt (_parameters.in.shmid, client);
break;
case SHMOP_shmctl:
@@ -726,6 +912,7 @@ client_request_shm::serve (transport_layer_base *const conn,
break;
}
+ client->release ();
conn->revert_to_self ();
if (result < 0)
diff --git a/winsup/cygwin/include/cygwin/cygserver_process.h b/winsup/cygwin/include/cygwin/cygserver_process.h
index 53da198af..85721709a 100755
--- a/winsup/cygwin/include/cygwin/cygserver_process.h
+++ b/winsup/cygwin/include/cygwin/cygserver_process.h
@@ -45,7 +45,7 @@ public:
virtual ~cleanup_routine ();
/* MUST BE SYNCHRONOUS */
- virtual void cleanup (DWORD winpid) = 0;
+ virtual void cleanup (const class process *) = 0;
private:
cleanup_routine *_next;
@@ -59,26 +59,30 @@ class process
friend process_cleanup;
public:
- process (DWORD winpid);
+ process (pid_t cygpid, DWORD winpid);
~process ();
+ pid_t cygpid () const { return _cygpid; }
+ DWORD winpid () const { return _winpid; }
HANDLE handle () const { return _hProcess; }
void hold () { EnterCriticalSection (&_access); }
void release () { LeaveCriticalSection (&_access); }
+ bool add (cleanup_routine *);
+
private:
+ const pid_t _cygpid;
const DWORD _winpid;
- class process *_next;
+ HANDLE _hProcess;
long _cleaning_up;
- cleanup_routine *_routines_head;
DWORD _exit_status; // Set in the constructor and in exit_code ().
- HANDLE _hProcess;
+ cleanup_routine *_routines_head;
/* used to prevent races-on-delete */
CRITICAL_SECTION _access;
+ class process *_next;
DWORD exit_code ();
- bool add (cleanup_routine *);
void cleanup ();
};
@@ -112,7 +116,7 @@ public:
process_cache (unsigned int initial_workers);
~process_cache ();
- class process *process (DWORD winpid);
+ class process *process (pid_t cygpid, DWORD winpid);
bool running () const { return _queue.running (); }
diff --git a/winsup/cygwin/include/sys/shm.h b/winsup/cygwin/include/sys/shm.h
index f800454da..01d50d051 100644
--- a/winsup/cygwin/include/sys/shm.h
+++ b/winsup/cygwin/include/sys/shm.h
@@ -36,7 +36,7 @@ extern "C"
/* Unsigned integer used for the number of current attaches.
*/
-typedef long int shmatt_t;
+typedef unsigned int shmatt_t;
struct shmid_ds
{
@@ -78,6 +78,8 @@ struct shm_info
{
unsigned long shm_ids; /* Number of allocated segments. */
unsigned long shm_tot; /* Size in bytes of allocated segments. */
+ unsigned long shm_atts; /* Number of attached segments, system
+ wide. */
};
void *shmat (int shmid, const void *shmaddr, int shmflg);