summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2014-07-01 20:00:48 +0200
committerMiloslav Trmač <mitr@redhat.com>2015-06-19 04:30:54 +0200
commitd7da6a23766e9c95fa333a0a9c742f7397c0ad22 (patch)
treef72e300940e466c641a13667b8ce5e495637b330
parentb544f10dd469ae3cfedc026db71ee76e9ef511a2 (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.c23
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);