@@ -427,23 +427,35 @@ impl<C: RenderConfiguration> Zone<C> {
427427 /// The worker performs its own teardown on exit (emits `TabClosed`, drops the
428428 /// tab's session storage). Returns `false` when the tab is unknown.
429429 pub async fn close_tab ( & mut self , tab_id : TabId ) -> bool {
430- let Some ( info) = self . tabs . remove ( & tab_id) else {
431- return false ;
432- } ;
433-
434- // A send error means the worker already exited; awaiting the join handle is
435- // still correct in that case.
436- let _ = info. cmd_tx . send ( TabCommand :: CloseTab ) . await ;
430+ match self . detach_tab ( tab_id) {
431+ Some ( closing) => {
432+ closing. await ;
433+ true
434+ }
435+ None => false ,
436+ }
437+ }
437438
439+ /// Takes a tab out of the zone, so it no longer counts against `max_tabs`, and
440+ /// returns the stopping of it: a future that asks the worker to stop and waits for
441+ /// it to exit. For a caller that cannot wait, such as a UI thread, which spawns it.
442+ /// Returns `None` when the tab is unknown.
443+ pub fn detach_tab ( & mut self , tab_id : TabId ) -> Option < impl std:: future:: Future < Output = ( ) > + Send + ' static > {
444+ let info = self . tabs . remove ( & tab_id) ?;
438445 let secs = self . context . config_store . get_uint ( "engine.io_shutdown_secs" ) as u64 ;
439- match tokio:: time:: timeout ( std:: time:: Duration :: from_secs ( secs) , info. join_handle ) . await {
440- Ok ( Ok ( ( ) ) ) => { }
441- Ok ( Err ( e) ) => log:: warn!( "Tab {tab_id} worker join error: {e}" ) ,
442- // The worker keeps running detached and cleans up whenever it exits.
443- Err ( _) => log:: warn!( "Tab {tab_id} worker did not stop within {secs}s" ) ,
444- }
445446
446- true
447+ Some ( async move {
448+ // A send error means the worker already exited; awaiting the join handle is
449+ // still correct in that case.
450+ let _ = info. cmd_tx . send ( TabCommand :: CloseTab ) . await ;
451+
452+ match tokio:: time:: timeout ( std:: time:: Duration :: from_secs ( secs) , info. join_handle ) . await {
453+ Ok ( Ok ( ( ) ) ) => { }
454+ Ok ( Err ( e) ) => log:: warn!( "Tab {tab_id} worker join error: {e}" ) ,
455+ // The worker keeps running detached and cleans up whenever it exits.
456+ Err ( _) => log:: warn!( "Tab {tab_id} worker did not stop within {secs}s" ) ,
457+ }
458+ } )
447459 }
448460
449461 /// Closes every tab in this zone. Used by `GosubEngine::close_zone`.
0 commit comments