File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -633,6 +633,37 @@ impl LocalSet {
633633 f ( )
634634 } )
635635 }
636+
637+ /// This method is like `with`, but it just calls `f` without setting the thread-local if that
638+ /// fails.
639+ fn with_if_possible < T > ( & self , f : impl FnOnce ( ) -> T ) -> T {
640+ let mut f = Some ( f) ;
641+
642+ let res = CURRENT . try_with ( |ctx| {
643+ struct Reset < ' a > {
644+ ctx_ref : & ' a Cell < Option < Rc < Context > > > ,
645+ val : Option < Rc < Context > > ,
646+ }
647+ impl < ' a > Drop for Reset < ' a > {
648+ fn drop ( & mut self ) {
649+ self . ctx_ref . replace ( self . val . take ( ) ) ;
650+ }
651+ }
652+ let old = ctx. replace ( Some ( self . context . clone ( ) ) ) ;
653+
654+ let _reset = Reset {
655+ ctx_ref : ctx,
656+ val : old,
657+ } ;
658+
659+ ( f. take ( ) . unwrap ( ) ) ( )
660+ } ) ;
661+
662+ match res {
663+ Ok ( res) => res,
664+ Err ( _access_error) => ( f. take ( ) . unwrap ( ) ) ( ) ,
665+ }
666+ }
636667}
637668
638669cfg_unstable ! {
@@ -744,7 +775,7 @@ impl Default for LocalSet {
744775
745776impl Drop for LocalSet {
746777 fn drop ( & mut self ) {
747- self . with ( || {
778+ self . with_if_possible ( || {
748779 // Shut down all tasks in the LocalOwnedTasks and close it to
749780 // prevent new tasks from ever being added.
750781 self . context . owned . close_and_shutdown_all ( ) ;
Original file line number Diff line number Diff line change @@ -311,6 +311,27 @@ fn join_local_future_elsewhere() {
311311 } ) ;
312312}
313313
314+ // Tests for <https://github.com/tokio-rs/tokio/issues/4973>
315+ #[ cfg( not( tokio_wasi) ) ] // Wasi doesn't support threads
316+ #[ tokio:: test( flavor = "multi_thread" ) ]
317+ async fn localset_in_thread_local ( ) {
318+ thread_local ! {
319+ static LOCAL_SET : LocalSet = LocalSet :: new( ) ;
320+ }
321+
322+ // holds runtime thread until end of main fn.
323+ let ( _tx, rx) = oneshot:: channel :: < ( ) > ( ) ;
324+ let handle = tokio:: runtime:: Handle :: current ( ) ;
325+
326+ std:: thread:: spawn ( move || {
327+ LOCAL_SET . with ( |local_set| {
328+ handle. block_on ( local_set. run_until ( async move {
329+ let _ = rx. await ;
330+ } ) )
331+ } ) ;
332+ } ) ;
333+ }
334+
314335#[ test]
315336fn drop_cancels_tasks ( ) {
316337 use std:: rc:: Rc ;
You can’t perform that action at this time.
0 commit comments