diff options
author | Miloslav Trmač <mitr@redhat.com> | 2014-07-01 20:00:48 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2015-06-19 04:30:54 +0200 |
commit | d7da6a23766e9c95fa333a0a9c742f7397c0ad22 (patch) | |
tree | f72e300940e466c641a13667b8ce5e495637b330 | |
parent | b544f10dd469ae3cfedc026db71ee76e9ef511a2 (diff) |
Fix spurious timeout exceptions on GC
The JS “Operation callback” can be called by the runtime for other
reasons, not only when we trigger it by a timeout—notably as part of GC.
So, make sure to only raise an exception if there actually was a
timeout.
Adding a whole extra mutex to protect a single boolean is somewhat of an
overkill, but better than worrying about “subtle bugs and occasionally
undefined behaviour” the g_atomic_* API is warning about.
https://bugs.freedesktop.org/show_bug.cgi?id=69501
also
https://bugs.freedesktop.org/show_bug.cgi?id=77524
-rw-r--r-- | src/polkitbackend/polkitbackendjsauthority.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c index 8a0a097..097dcc5 100644 --- a/src/polkitbackend/polkitbackendjsauthority.c +++ b/src/polkitbackend/polkitbackendjsauthority.c @@ -80,6 +80,8 @@ struct _PolkitBackendJsAuthorityPrivate GMainContext *rkt_context; GMainLoop *rkt_loop; GSource *rkt_source; + GMutex rkt_timeout_pending_mutex; + gboolean rkt_timeout_pending; /* A list of JSObject instances */ GList *scripts; @@ -528,6 +530,7 @@ polkit_backend_js_authority_constructed (GObject *object) g_mutex_init (&authority->priv->rkt_init_mutex); g_cond_init (&authority->priv->rkt_init_cond); + g_mutex_init (&authority->priv->rkt_timeout_pending_mutex); authority->priv->runaway_killer_thread = g_thread_new ("runaway-killer-thread", runaway_killer_thread_func, @@ -563,6 +566,7 @@ polkit_backend_js_authority_finalize (GObject *object) g_mutex_clear (&authority->priv->rkt_init_mutex); g_cond_clear (&authority->priv->rkt_init_cond); + g_mutex_clear (&authority->priv->rkt_timeout_pending_mutex); /* shut down the killer thread */ g_assert (authority->priv->rkt_loop != NULL); @@ -957,6 +961,18 @@ js_operation_callback (JSContext *cx) JSString *val_str; jsval val; + /* This callback can be called by the runtime at any time without us causing + * it by JS_TriggerOperationCallback(). + */ + g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex); + if (!authority->priv->rkt_timeout_pending) + { + g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex); + return JS_TRUE; + } + authority->priv->rkt_timeout_pending = FALSE; + g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex); + /* Log that we are terminating the script */ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority), "Terminating runaway script"); @@ -974,6 +990,10 @@ rkt_on_timeout (gpointer user_data) { PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data); + g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex); + authority->priv->rkt_timeout_pending = TRUE; + g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex); + /* Supposedly this is thread-safe... */ #if JS_VERSION == 186 JS_TriggerOperationCallback (authority->priv->rt); @@ -993,6 +1013,9 @@ runaway_killer_setup (PolkitBackendJsAuthority *authority) g_assert (authority->priv->rkt_source == NULL); /* set-up timer for runaway scripts, will be executed in runaway_killer_thread */ + g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex); + authority->priv->rkt_timeout_pending = FALSE; + g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex); authority->priv->rkt_source = g_timeout_source_new_seconds (15); g_source_set_callback (authority->priv->rkt_source, rkt_on_timeout, authority, NULL); g_source_attach (authority->priv->rkt_source, authority->priv->rkt_context); |