Author: dick
Date: 2006-03-24 11:37:02 -0500 (Fri, 24 Mar 2006)
New Revision: 58432
Modified:
branches/mono-1-1-13/mono/mono/io-layer/ChangeLog
branches/mono-1-1-13/mono/mono/io-layer/handles.c
branches/mono-1-1-13/mono/mono/io-layer/shared.c
branches/mono-1-1-13/mono/mono/io-layer/shared.h
branches/mono-1-1-13/mono/mono/io-layer/wapi-private.h
Log:
2006-03-22 Dick Porter <[EMAIL PROTECTED]>
* handles.c:
* wapi-private.h:
* shared.h:
* shared.c: Delete the semaphores and shared files when the last
process has finished with them
Modified: branches/mono-1-1-13/mono/mono/io-layer/ChangeLog
===================================================================
--- branches/mono-1-1-13/mono/mono/io-layer/ChangeLog 2006-03-24 16:36:28 UTC
(rev 58431)
+++ branches/mono-1-1-13/mono/mono/io-layer/ChangeLog 2006-03-24 16:37:02 UTC
(rev 58432)
@@ -1,3 +1,11 @@
+2006-03-22 Dick Porter <[EMAIL PROTECTED]>
+
+ * handles.c:
+ * wapi-private.h:
+ * shared.h:
+ * shared.c: Delete the semaphores and shared files when the last
+ process has finished with them
+
2006-03-15 Dick Porter <[EMAIL PROTECTED]>
* events.c:
Modified: branches/mono-1-1-13/mono/mono/io-layer/handles.c
===================================================================
--- branches/mono-1-1-13/mono/mono/io-layer/handles.c 2006-03-24 16:36:28 UTC
(rev 58431)
+++ branches/mono-1-1-13/mono/mono/io-layer/handles.c 2006-03-24 16:37:02 UTC
(rev 58432)
@@ -4,7 +4,7 @@
* Author:
* Dick Porter ([EMAIL PROTECTED])
*
- * (C) 2002-2006 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
*/
#include <config.h>
@@ -132,6 +132,11 @@
static mono_mutex_t scan_mutex = MONO_MUTEX_INITIALIZER;
+static void handle_cleanup (void)
+{
+ _wapi_shm_semaphores_remove ();
+}
+
static mono_once_t shared_init_once = MONO_ONCE_INIT;
static void shared_init (void)
{
@@ -149,11 +154,11 @@
_wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
} while(_wapi_fd_reserve > _wapi_private_handle_count);
+
+ _wapi_shm_semaphores_init ();
_wapi_shared_layout = _wapi_shm_attach (WAPI_SHM_DATA);
g_assert (_wapi_shared_layout != NULL);
-
- _wapi_shm_semaphores_init ();
_wapi_fileshare_layout = _wapi_shm_attach (WAPI_SHM_FILESHARE);
g_assert (_wapi_fileshare_layout != NULL);
@@ -165,6 +170,13 @@
thr_ret = mono_mutex_init(&_wapi_global_signal_mutex, NULL);
g_assert (thr_ret == 0);
+
+ /* Using g_atexit here instead of an explicit function call in
+ * a cleanup routine lets us cope when a third-party library
+ * calls exit (eg if an X client loses the connection to its
+ * server.)
+ */
+ g_atexit (handle_cleanup);
}
static void _wapi_handle_init_shared (struct _WapiHandleShared *handle,
@@ -1709,3 +1721,4 @@
_wapi_handle_unlock_shared_handles ();
}
+
Modified: branches/mono-1-1-13/mono/mono/io-layer/shared.c
===================================================================
--- branches/mono-1-1-13/mono/mono/io-layer/shared.c 2006-03-24 16:36:28 UTC
(rev 58431)
+++ branches/mono-1-1-13/mono/mono/io-layer/shared.c 2006-03-24 16:37:02 UTC
(rev 58432)
@@ -4,7 +4,7 @@
* Author:
* Dick Porter ([EMAIL PROTECTED])
*
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
*/
@@ -34,7 +34,7 @@
static guchar file[_POSIX_PATH_MAX];
guchar *name = NULL, *filename, *dir, *wapi_dir;
gchar machine_name[256];
- gchar *fake_name;
+ const gchar *fake_name;
struct utsname ubuf;
int ret;
int len;
@@ -259,9 +259,11 @@
void _wapi_shm_semaphores_init ()
{
- key_t key = ftok (_wapi_shm_file (WAPI_SHM_DATA), 'M');
+ key_t key;
key_t oldkey;
-
+ int thr_ret;
+ struct _WapiHandleSharedLayout *tmp_shared;
+
/* Yet more barmy API - this union is a well-defined parameter
* in a syscall, yet I still have to define it here as it
* doesn't appear in a header
@@ -278,11 +280,31 @@
for (i = 0; i < _WAPI_SHARED_SEM_COUNT; i++) {
def_vals[i] = 1;
}
+#ifdef NEXT_VERSION_INC
+ /* Process count must start at '0' - the 1 for all the others
+ * sets the semaphore to "unlocked"
+ */
+ def_vals[_WAPI_SHARED_SEM_PROCESS_COUNT] = 0;
+#endif
+
defs.array = def_vals;
+ /* Temporarily attach the shared data so we can read the
+ * semaphore key. We release this mapping and attach again
+ * after getting the semaphores to avoid a race condition
+ * where a terminating process can delete the shared files
+ * between a new process attaching the file and getting access
+ * to the semaphores (which increments the process count,
+ * preventing destruction of the shared data...)
+ */
+ tmp_shared = _wapi_shm_attach (WAPI_SHM_DATA);
+ g_assert (tmp_shared != NULL);
+
+ key = ftok (_wapi_shm_file (WAPI_SHM_DATA), 'M');
+
again:
retries++;
- oldkey = _wapi_shared_layout->sem_key;
+ oldkey = tmp_shared->sem_key;
if (oldkey == 0) {
#ifdef DEBUG
@@ -328,7 +350,7 @@
goto again;
}
- if (InterlockedCompareExchange (&_wapi_shared_layout->sem_key,
+ if (InterlockedCompareExchange (&tmp_shared->sem_key,
key, 0) != 0) {
/* Someone else created one and installed the
* key while we were working, so delete the
@@ -336,12 +358,12 @@
* 'key already known' case.
*/
semctl (_wapi_sem_id, 0, IPC_RMID);
- oldkey = _wapi_shared_layout->sem_key;
+ oldkey = tmp_shared->sem_key;
} else {
/* We've installed this semaphore set's key into
* the shared memory
*/
- return;
+ goto done;
}
}
@@ -358,13 +380,82 @@
/* Someone must have deleted the semaphore set, so
* blow away the bad key and try again
*/
- InterlockedCompareExchange (&_wapi_shared_layout->sem_key, 0,
- oldkey);
+ InterlockedCompareExchange (&tmp_shared->sem_key, 0, oldkey);
goto again;
}
+
+ done:
+ /* Increment the usage count of this semaphore set */
+ thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
+ g_assert (thr_ret == 0);
+
+#ifdef DEBUG
+ g_message ("%s: Incrementing the process count", __func__);
+#endif
+
+ /* We only ever _unlock_ this semaphore, letting the kernel
+ * restore (ie decrement) this unlock when this process exits.
+ * We lock another semaphore around it so we can serialise
+ * access when we're testing the value of this semaphore when
+ * we exit cleanly, so we can delete the whole semaphore set.
+ */
+ _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT);
+
+#ifdef DEBUG
+ g_message ("%s: Process count is now %d", __func__, semctl
(_wapi_sem_id, _WAPI_SHARED_SEM_PROCESS_COUNT, GETVAL));
+#endif
+
+ _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
+
+ munmap (tmp_shared, sizeof(struct _WapiHandleSharedLayout));
}
+void _wapi_shm_semaphores_remove (void)
+{
+ int thr_ret;
+ int proc_count;
+
+#ifdef DEBUG
+ g_message ("%s: Checking process count", __func__);
+#endif
+
+ thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
+ g_assert (thr_ret == 0);
+
+ proc_count = semctl (_wapi_sem_id, _WAPI_SHARED_SEM_PROCESS_COUNT,
+ GETVAL);
+#ifdef NEXT_VERSION_INC
+ g_assert (proc_count > 0);
+ if (proc_count == 1) {
+#else
+ /* Compatibility - the semaphore was initialised to '1' (which
+ * normally means 'unlocked'. Instead of fixing that right
+ * now, which would mean a shared file version increment, just
+ * cope with the value starting too high for now. Fix this
+ * next time I have to change the file version.
+ */
+ g_assert (proc_count > 1);
+ if (proc_count == 2) {
+#endif
+ /* Just us, so blow away the semaphores and the shared
+ * files
+ */
+#ifdef DEBUG
+ g_message ("%s: Removing semaphores!", __func__);
+#endif
+
+ semctl (_wapi_sem_id, IPC_RMID, 0);
+ unlink (_wapi_shm_file (WAPI_SHM_DATA));
+ unlink (_wapi_shm_file (WAPI_SHM_FILESHARE));
+ } else {
+ /* "else" clause, because there's no point unlocking
+ * the semaphore if we've just blown it away...
+ */
+ _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
+ }
+}
+
int _wapi_shm_sem_lock (int sem)
{
struct sembuf ops;
@@ -378,11 +469,28 @@
ops.sem_op = -1;
ops.sem_flg = SEM_UNDO;
+ retry:
do {
ret = semop (_wapi_sem_id, &ops, 1);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
+ /* EINVAL covers the case when the semaphore was
+ * deleted before we started the semop
+ */
+ if (errno == EIDRM || errno == EINVAL) {
+ /* Someone blew away this semaphore set, so
+ * get a new one and try again
+ */
+#ifdef DEBUG
+ g_message ("%s: Reinitialising the semaphores!",
+ __func__);
+#endif
+
+ _wapi_shm_semaphores_init ();
+ goto retry;
+ }
+
/* Turn this into a pthreads-style return value */
ret = errno;
}
@@ -407,11 +515,28 @@
ops.sem_op = -1;
ops.sem_flg = IPC_NOWAIT | SEM_UNDO;
+ retry:
do {
ret = semop (_wapi_sem_id, &ops, 1);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
+ /* EINVAL covers the case when the semaphore was
+ * deleted before we started the semop
+ */
+ if (errno == EIDRM || errno == EINVAL) {
+ /* Someone blew away this semaphore set, so
+ * get a new one and try again
+ */
+#ifdef DEBUG
+ g_message ("%s: Reinitialising the semaphores!",
+ __func__);
+#endif
+
+ _wapi_shm_semaphores_init ();
+ goto retry;
+ }
+
/* Turn this into a pthreads-style return value */
ret = errno;
}
@@ -441,11 +566,29 @@
ops.sem_op = 1;
ops.sem_flg = SEM_UNDO;
+ retry:
do {
ret = semop (_wapi_sem_id, &ops, 1);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
+ /* EINVAL covers the case when the semaphore was
+ * deleted before we started the semop
+ */
+ if (errno == EIDRM || errno == EINVAL) {
+ /* Someone blew away this semaphore set, so
+ * get a new one and try again (we can't just
+ * assume that the semaphore is now unlocked)
+ */
+#ifdef DEBUG
+ g_message ("%s: Reinitialising the semaphores!",
+ __func__);
+#endif
+
+ _wapi_shm_semaphores_init ();
+ goto retry;
+ }
+
/* Turn this into a pthreads-style return value */
ret = errno;
}
Modified: branches/mono-1-1-13/mono/mono/io-layer/shared.h
===================================================================
--- branches/mono-1-1-13/mono/mono/io-layer/shared.h 2006-03-24 16:36:28 UTC
(rev 58431)
+++ branches/mono-1-1-13/mono/mono/io-layer/shared.h 2006-03-24 16:37:02 UTC
(rev 58432)
@@ -4,7 +4,7 @@
* Author:
* Dick Porter ([EMAIL PROTECTED])
*
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
*/
#ifndef _WAPI_SHARED_H_
@@ -19,6 +19,7 @@
extern gpointer _wapi_shm_attach (_wapi_shm_t type);
extern void _wapi_shm_semaphores_init (void);
+extern void _wapi_shm_semaphores_remove (void);
extern int _wapi_shm_sem_lock (int sem);
extern int _wapi_shm_sem_trylock (int sem);
extern int _wapi_shm_sem_unlock (int sem);
Modified: branches/mono-1-1-13/mono/mono/io-layer/wapi-private.h
===================================================================
--- branches/mono-1-1-13/mono/mono/io-layer/wapi-private.h 2006-03-24
16:36:28 UTC (rev 58431)
+++ branches/mono-1-1-13/mono/mono/io-layer/wapi-private.h 2006-03-24
16:37:02 UTC (rev 58432)
@@ -4,7 +4,7 @@
* Author:
* Dick Porter ([EMAIL PROTECTED])
*
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
*/
#ifndef _WAPI_PRIVATE_H_
@@ -24,6 +24,7 @@
/* Increment this whenever an incompatible change is made to the
* shared handle structure.
*/
+/* Next time I change this, remember to fix the process count in shared.c */
#define _WAPI_HANDLE_VERSION 10
typedef enum {
@@ -165,6 +166,8 @@
/*#define _WAPI_SHARED_SEM_COLLECTION 1*/
#define _WAPI_SHARED_SEM_FILESHARE 2
#define _WAPI_SHARED_SEM_SHARED_HANDLES 3
+#define _WAPI_SHARED_SEM_PROCESS_COUNT_LOCK 6
+#define _WAPI_SHARED_SEM_PROCESS_COUNT 7
#define _WAPI_SHARED_SEM_COUNT 8 /* Leave some future expansion space */
struct _WapiHandleSharedLayout
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches