Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Worklet can access ScriptThread TLS after it's no longer valid #25838

Open
jdm opened this issue Feb 24, 2020 · 2 comments
Open

Worklet can access ScriptThread TLS after it's no longer valid #25838

jdm opened this issue Feb 24, 2020 · 2 comments

Comments

@jdm
Copy link
Member

@jdm jdm commented Feb 24, 2020

This can cause panics if a GC occurs after the ScriptThread code has cleaned up the TLS:

impl Drop for Worklet {
fn drop(&mut self) {
let script_thread = ScriptThread::worklet_thread_pool();
script_thread.exit_worklet(self.worklet_id);
}
}

@jdm
Copy link
Member Author

@jdm jdm commented Feb 24, 2020

diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs
index 227d9d97c8..e823db830c 100644
--- a/components/script/dom/worklet.rs
+++ b/components/script/dom/worklet.rs
@@ -78,6 +78,8 @@ pub struct Worklet {
     window: Dom<Window>,
     worklet_id: WorkletId,
     global_type: WorkletGlobalScopeType,
+    #[ignore_malloc_size_of = "rc is hard"]
+    thread_pool: Rc<WorkletThreadPool>,
 }

 impl Worklet {
@@ -87,6 +89,7 @@ impl Worklet {
             window: Dom::from_ref(window),
             worklet_id: WorkletId::new(),
             global_type: global_type,
+            thread_pool: ScriptThread::worklet_thread_pool(),
         }
     }

@@ -136,9 +139,8 @@ impl WorkletMethods for Worklet {
         // Steps 6-12 in parallel.
         let pending_tasks_struct = PendingTasksStruct::new();
         let global = self.window.upcast::<GlobalScope>();
-        let pool = ScriptThread::worklet_thread_pool();

-        pool.fetch_and_invoke_a_worklet_script(
+        self.thread_pool.fetch_and_invoke_a_worklet_script(
             global.pipeline_id(),
             self.worklet_id,
             self.global_type,
@@ -158,8 +160,7 @@ impl WorkletMethods for Worklet {

 impl Drop for Worklet {
     fn drop(&mut self) {
-        let script_thread = ScriptThread::worklet_thread_pool();
-        script_thread.exit_worklet(self.worklet_id);
+        self.thread_pool.exit_worklet(self.worklet_id);
     }
 }

@@ -504,9 +505,13 @@ impl WorkletThread {
                 //       this total ordering on thread roles is what guarantees deadlock-freedom.
                 WorkletData::StartSwapRoles(sender) => {
                     let (our_swapper, their_swapper) = swapper();
-                    sender
+                    if sender
                         .send(WorkletData::FinishSwapRoles(their_swapper))
-                        .unwrap();
+                        .is_err()
+                    {
+                        warn!("Couldn't complete swap; exiting worklet event loop.");
+                        return;
+                    }
                     let _ = our_swapper.swap(&mut self.role);
                 },
                 // To finish swapping roles, perform the atomic swap.

This was an attempt to correct it in #25345, but a lot of css-paint-api tests started timing out for reasons that were not clear to me, so this patch was not merged.

@gterzian
Copy link
Member

@gterzian gterzian commented Feb 25, 2020

The only thing I can think of, is that the patch was doing ScriptThread::worklet_thread_pool() in the Worklet constructor, wherease previously it was done only "lazily" when AddModule was called.

It could be worth a shot having the worklet own an Option<Rc<WorkletThreadPool>>, and in AddModule initializing it to something if it hasn't been initialized already, while setting it to none in the constructor.

@jdm jdm added the C-has-patch label Feb 25, 2020
@jdm jdm changed the title Workelet can access ScriptThread TLS after it's no longer valid Worklet can access ScriptThread TLS after it's no longer valid Mar 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.