Revert "gcancellable: allow g_cancellable_disconnect from "cancelled" handler on same thread"

This reverts commits 83605e2d0a7b0d39987715cfd046f7b8ef6de94e and
140fa7ee4669adb3827e3ddea5be57f51ee7af3e.
This commit is contained in:
Ryan Lortie 2013-09-23 16:15:34 -04:00
parent 140fa7ee46
commit 6d08d1191b

View File

@ -46,8 +46,8 @@ enum {
struct _GCancellablePrivate struct _GCancellablePrivate
{ {
guint cancelled : 1; guint cancelled : 1;
guint cancelled_running : 1;
guint cancelled_running_waiting : 1; guint cancelled_running_waiting : 1;
GThread *cancelled_running_thread;
guint fd_refcount; guint fd_refcount;
GWakeup *wakeup; GWakeup *wakeup;
@ -122,7 +122,7 @@ g_cancellable_class_init (GCancellableClass *klass)
* if (cancellable) * if (cancellable)
* id = g_cancellable_connect (cancellable, * id = g_cancellable_connect (cancellable,
* G_CALLBACK (cancelled_handler) * G_CALLBACK (cancelled_handler)
* my_data, NULL); * data, NULL);
* *
* /<!-- -->* cancellable operation here... *<!-- -->/ * /<!-- -->* cancellable operation here... *<!-- -->/
* *
@ -260,8 +260,7 @@ g_cancellable_reset (GCancellable *cancellable)
priv = cancellable->priv; priv = cancellable->priv;
while (priv->cancelled_running_thread != NULL && while (priv->cancelled_running)
priv->cancelled_running_thread != g_thread_self ())
{ {
priv->cancelled_running_waiting = TRUE; priv->cancelled_running_waiting = TRUE;
g_cond_wait (&cancellable_cond, &cancellable_mutex); g_cond_wait (&cancellable_cond, &cancellable_mutex);
@ -493,7 +492,7 @@ g_cancellable_cancel (GCancellable *cancellable)
} }
priv->cancelled = TRUE; priv->cancelled = TRUE;
priv->cancelled_running_thread = g_thread_self (); priv->cancelled_running = TRUE;
if (priv->wakeup) if (priv->wakeup)
GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup); GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
@ -505,7 +504,7 @@ g_cancellable_cancel (GCancellable *cancellable)
g_mutex_lock (&cancellable_mutex); g_mutex_lock (&cancellable_mutex);
priv->cancelled_running_thread = NULL; priv->cancelled_running = FALSE;
if (priv->cancelled_running_waiting) if (priv->cancelled_running_waiting)
g_cond_broadcast (&cancellable_cond); g_cond_broadcast (&cancellable_cond);
priv->cancelled_running_waiting = FALSE; priv->cancelled_running_waiting = FALSE;
@ -558,8 +557,6 @@ g_cancellable_connect (GCancellable *cancellable,
void (*_callback) (GCancellable *cancellable, void (*_callback) (GCancellable *cancellable,
gpointer user_data); gpointer user_data);
g_mutex_unlock (&cancellable_mutex);
_callback = (void *)callback; _callback = (void *)callback;
id = 0; id = 0;
@ -574,10 +571,9 @@ g_cancellable_connect (GCancellable *cancellable,
callback, data, callback, data,
(GClosureNotify) data_destroy_func, (GClosureNotify) data_destroy_func,
0); 0);
g_mutex_unlock (&cancellable_mutex);
} }
g_mutex_unlock (&cancellable_mutex);
return id; return id;
} }
@ -588,20 +584,17 @@ g_cancellable_connect (GCancellable *cancellable,
* @handler_id: Handler id of the handler to be disconnected, or %0. * @handler_id: Handler id of the handler to be disconnected, or %0.
* *
* Disconnects a handler from a cancellable instance similar to * Disconnects a handler from a cancellable instance similar to
* g_signal_handler_disconnect(). Additionally, in the event that a * g_signal_handler_disconnect(). Additionally, in the event that a
* signal handler is currently running on a different thread, this * signal handler is currently running, this call will block until the
* call will block until the handler has finished. * handler has finished. Calling this function from a
* #GCancellable::cancelled signal handler will therefore result in a
* deadlock.
* *
* This avoids a race condition where a thread cancels at the * This avoids a race condition where a thread cancels at the
* same time as the cancellable operation is finished and the * same time as the cancellable operation is finished and the
* signal handler is removed. See #GCancellable::cancelled for * signal handler is removed. See #GCancellable::cancelled for
* details on how to use this. * details on how to use this.
* *
* Note, since 2.38 it is safe to call this function from a
* #GCancellable::cancelled signal handler, something which would
* previously have caused a deadlock. However, it is not a good idea
* to disconnect a signal handler from inside its *own* signal handler.
*
* If @cancellable is %NULL or @handler_id is %0 this function does * If @cancellable is %NULL or @handler_id is %0 this function does
* nothing. * nothing.
* *
@ -620,8 +613,7 @@ g_cancellable_disconnect (GCancellable *cancellable,
priv = cancellable->priv; priv = cancellable->priv;
while (priv->cancelled_running_thread != NULL && while (priv->cancelled_running)
priv->cancelled_running_thread != g_thread_self ())
{ {
priv->cancelled_running_waiting = TRUE; priv->cancelled_running_waiting = TRUE;
g_cond_wait (&cancellable_cond, &cancellable_mutex); g_cond_wait (&cancellable_cond, &cancellable_mutex);