Skip to content

Timers: remove send bound on boxed timer callback#37983

Open
gterzian wants to merge 3 commits intoservo:mainfrom
gterzian:remove_send_bound_on_timer_callback
Open

Timers: remove send bound on boxed timer callback#37983
gterzian wants to merge 3 commits intoservo:mainfrom
gterzian:remove_send_bound_on_timer_callback

Conversation

@gterzian
Copy link
Copy Markdown
Member

@gterzian gterzian commented Jul 10, 2025

But introduce a new send-able callback for use in refresh driver.

This then enables switching to an cell for has_pending_animation_tick in the script-thread, which uses no threading to schedule timers.

Fix #37946

…ndable callback for use in refresh driver

Signed-off-by: gterzian <[email protected]>
@gterzian gterzian force-pushed the remove_send_bound_on_timer_callback branch from 6cddd81 to c97eccf Compare July 10, 2025 15:13
@gterzian gterzian force-pushed the remove_send_bound_on_timer_callback branch from c97eccf to 869e669 Compare July 10, 2025 15:13
@gterzian gterzian marked this pull request as ready for review July 10, 2025 15:14
@gterzian gterzian requested a review from mrobinson as a code owner July 10, 2025 15:14
@gterzian gterzian changed the title Timers: remove the send bound on boxed timer callback Timers: remove send bound on boxed timer callback Jul 10, 2025
Signed-off-by: gterzian <[email protected]>
@gterzian gterzian force-pushed the remove_send_bound_on_timer_callback branch from ebdce4d to 75bdaad Compare July 10, 2025 15:21
@jdm
Copy link
Copy Markdown
Member

jdm commented Jul 10, 2025

I'd like to look at this before it merges. I want to make sure the changes don't open a hole in our GC story for values captured in task closures.

@jdm
Copy link
Copy Markdown
Member

jdm commented Jul 10, 2025

I don't believe this is safe right now.

  1. ScriptThread::timer_scheduler is marked no_trace
  2. the scheduler contains BoxedTimerCallback values that can move arbitrary values into a closure
  3. as long as those callbacks were required to be Send, we could rely on none of our GC types being Send and therefore preventing GC values stored in an opaque closure. Now we're lifting that restriction but the scheduler is still opaque to the GC

Copy link
Copy Markdown
Member

@jdm jdm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to fix the soundness hole before merging these changes. This overlaps a lot with my work in #37762.

Copy link
Copy Markdown
Member

@mrobinson mrobinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong opinion on this, so if soundness issues are addressed it seems reasonable:

scheduler.schedule_timer(request);
},
let (callback, duration) = match message {
Ok(TimerThreadMessage::Request(cb, dur)) => (cb, dur),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
Ok(TimerThreadMessage::Request(cb, dur)) => (cb, dur),
Ok(TimerThreadMessage::Request(callback, duration)) => (callback, duration),

@gterzian
Copy link
Copy Markdown
Member Author

gterzian commented Jul 11, 2025

I don't believe this is safe right now.

Ok I see, so basically the current changes are in fact safe, because the cell is not a rooted type, but for example my suggestions at #37984 (using a Dom<GlobalScope> in a callback) would be definitely a bad idea(but the current code is safe, because it uses Trusted).

Thanks for catching this.

If we were to use the NonSendTaskOnce proposed at #37762, then we'd need to have a script specific timer scheduler that would be js traceable, right?

How about separating the queue of callbacks from the timer scheduler itself?

For example:

  • schedule_timer take a usize(and a duration), which is the position of the callback in the queue.
  • dispatch_completed_timers returns a list of positions. It's up to the surrounding environment to then dispatch the assosiated callbacks. This would mean that in script we can store the callbacks somewhere where they will be traced.

EDIT: obviously one would use a hasmap, not a queue, since timers fire independently of their position in any queue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rendering loop: replace the Arc<AtomicBool> with a Cell<bool> for has_pending_animation_tick in ScriptThread

4 participants