@@ -88,7 +88,7 @@ use libc::{SIGFPE, SIGILL, SIGKILL, SIGSEGV, SIGSTOP};
8888use libc:: { SIGFPE , SIGILL , SIGSEGV } ;
8989
9090use half_lock:: HalfLock ;
91- use vec_map:: { Entry , VecMap } ;
91+ use vec_map:: VecMap ;
9292
9393// These constants are not defined in the current version of libc, but it actually
9494// exists in Windows CRT.
@@ -630,34 +630,32 @@ unsafe fn register_unchecked_impl(signal: c_int, action: Arc<Action>) -> Result<
630630 let id = ActionId ( sigdata. next_id ) ;
631631 sigdata. next_id += 1 ;
632632
633- match sigdata. signals . entry ( signal) {
634- Entry :: Occupied ( mut occupied) => {
635- assert ! ( occupied. get_mut( ) . actions. insert( id, action) . is_none( ) ) ;
636- }
637- Entry :: Vacant ( place) => {
638- // While the sigaction/signal exchanges the old one atomically, we are not able to
639- // atomically store it somewhere a signal handler could read it. That poses a race
640- // condition where we could lose some signals delivered in between changing it and
641- // storing it.
642- //
643- // Therefore we first store the old one in the fallback storage. The fallback only
644- // covers the cases where the slot is not yet active and becomes "inert" after that,
645- // even if not removed (it may get overwritten by some other signal, but for that the
646- // mutex in globals.data must be unlocked here - and by that time we already stored the
647- // slot.
648- //
649- // And yes, this still leaves a short race condition when some other thread could
650- // replace the signal handler and we would be calling the outdated one for a short
651- // time, until we install the slot.
652- globals
653- . race_fallback
654- . write ( )
655- . store ( Some ( Prev :: detect ( signal) ?) ) ;
656-
657- let mut slot = Slot :: new ( signal) ?;
658- slot. actions . insert ( id, action) ;
659- place. insert ( slot) ;
660- }
633+ if sigdata. signals . contains ( & signal) {
634+ let slot = sigdata. signals . get_mut ( & signal) . unwrap ( ) ;
635+ assert ! ( slot. actions. insert( id, action) . is_none( ) ) ;
636+ } else {
637+ // While the sigaction/signal exchanges the old one atomically, we are not able to
638+ // atomically store it somewhere a signal handler could read it. That poses a race
639+ // condition where we could lose some signals delivered in between changing it and
640+ // storing it.
641+ //
642+ // Therefore we first store the old one in the fallback storage. The fallback only
643+ // covers the cases where the slot is not yet active and becomes "inert" after that,
644+ // even if not removed (it may get overwritten by some other signal, but for that the
645+ // mutex in globals.data must be unlocked here - and by that time we already stored the
646+ // slot.
647+ //
648+ // And yes, this still leaves a short race condition when some other thread could
649+ // replace the signal handler and we would be calling the outdated one for a short
650+ // time, until we install the slot.
651+ globals
652+ . race_fallback
653+ . write ( )
654+ . store ( Some ( Prev :: detect ( signal) ?) ) ;
655+
656+ let mut slot = Slot :: new ( signal) ?;
657+ slot. actions . insert ( id, action) ;
658+ sigdata. signals . insert ( signal, slot) ;
661659 }
662660
663661 lock. store ( sigdata) ;
0 commit comments