mono_os_mutex_unlock (&global_signal_mutex);
}
+static void
+mono_w32handle_ref (gpointer handle);
+
+static void
+mono_w32handle_unref (gpointer handle);
+
void
mono_w32handle_lock_handle (gpointer handle)
{
void
mono_w32handle_cleanup (void)
{
- int i, j, k;
+ int i;
g_assert (!shutting_down);
shutting_down = TRUE;
- /* Every shared handle we were using ought really to be closed
- * by now, but to make sure just blow them all away. The
- * exiting finalizer thread in particular races us to the
- * program exit and doesn't always win, so it can be left
- * cluttering up the shared file. Anything else left over is
- * really a bug.
- */
- for(i = SLOT_INDEX (0); private_handles[i] != NULL; i++) {
- for(j = SLOT_OFFSET (0); j < HANDLE_PER_SLOT; j++) {
- MonoW32HandleBase *handle_data = &private_handles[i][j];
- gpointer handle = GINT_TO_POINTER (i*HANDLE_PER_SLOT+j);
-
- for(k = handle_data->ref; k > 0; k--) {
- mono_w32handle_unref (handle);
- }
- }
- }
-
for (i = 0; i < SLOT_MAX; ++i)
g_free (private_handles [i]);
}
return(GUINT_TO_POINTER(fd));
}
+static gboolean
+mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
+
+static gboolean
+mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data);
+
+static void
+w32handle_destroy (gpointer handle);
+
+gpointer
+mono_w32handle_duplicate (gpointer handle)
+{
+ MonoW32HandleBase *handle_data;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return handle;
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return INVALID_HANDLE_VALUE;
+ if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE)
+ return handle;
+
+ if (!mono_w32handle_ref_core (handle, handle_data))
+ g_error ("%s: failed to ref handle %p", __func__, handle);
+
+ return handle;
+}
+
gboolean
mono_w32handle_close (gpointer handle)
{
+ MonoW32HandleBase *handle_data;
+ gboolean destroy;
+
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
- if (handle == (gpointer) 0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ return FALSE;
+ if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE) {
/* Problem: because we map file descriptors to the
* same-numbered handle we can't tell the difference
* between a bogus handle and the handle to stdin.
return FALSE;
}
- mono_w32handle_unref (handle);
+ destroy = mono_w32handle_unref_core (handle, handle_data);
+ if (destroy)
+ w32handle_destroy (handle);
+
return TRUE;
}
return(TRUE);
}
-static gboolean
-mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
-
-static gboolean
-mono_w32handle_unref_core (gpointer handle, MonoW32HandleBase *handle_data);
-
-static void
-w32handle_destroy (gpointer handle);
-
void
mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpointer user_data), gpointer user_data)
{
return new == 0;
}
-void mono_w32handle_ref (gpointer handle)
+static void
+mono_w32handle_ref (gpointer handle)
{
MonoW32HandleBase *handle_data;
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to ref handle %p, unknown handle", __func__, handle);
- return;
- }
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("%s: failed to ref handle %p, unknown handle", __func__, handle);
if (!mono_w32handle_ref_core (handle, handle_data))
g_error ("%s: failed to ref handle %p", __func__, handle);
}
/* The handle must not be locked on entry to this function */
-void
+static void
mono_w32handle_unref (gpointer handle)
{
MonoW32HandleBase *handle_data;
gboolean destroy;
- if (!mono_w32handle_lookup_data (handle, &handle_data)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to unref handle %p, unknown handle",
- __func__, handle);
- return;
- }
+ if (!mono_w32handle_lookup_data (handle, &handle_data))
+ g_error ("%s: failed to unref handle %p, unknown handle", __func__, handle);
destroy = mono_w32handle_unref_core (handle, handle_data);
if (destroy)
mono_os_cond_broadcast (cond);
mono_os_mutex_unlock (mutex);
- mono_w32handle_unref (handle);
+ mono_w32handle_close (handle);
}
static int
mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
{
MonoW32HandleBase *handle_data;
+ gpointer handle_duplicate;
int res;
if (!mono_w32handle_lookup_data (handle, &handle_data))
*alerted = FALSE;
if (alerted) {
- mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted);
- if (*alerted)
+ mono_thread_info_install_interrupt (signal_handle_and_unref, handle_duplicate = mono_w32handle_duplicate (handle), alerted);
+ if (*alerted) {
+ mono_w32handle_close (handle_duplicate);
return 0;
- mono_w32handle_ref (handle);
+ }
}
res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
if (alerted) {
mono_thread_info_uninstall_interrupt (alerted);
if (!*alerted) {
- /* if it is alerted, then the handle is unref in the interrupt callback */
- mono_w32handle_unref (handle);
+ /* if it is alerted, then the handle_duplicate is closed in the interrupt callback */
+ mono_w32handle_close (handle_duplicate);
}
}
g_error ("cannot dump unknown handle %p", handle);
g_print ("%p [%7s] signalled: %5s ref: %3d ",
- handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref);
+ handle, mono_w32handle_ops_typename (handle_data->type), handle_data->signalled ? "true" : "false", handle_data->ref - 1 /* foreach increase ref by 1 */);
mono_w32handle_ops_details (handle_data->type, handle_data->specific);
g_print ("\n");