diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 290380face9cc5fa442fd26c61e6d38a78bcc90c..337eb6a5dbeb1cd689abb6dfe564751d0ce88720 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -104,18 +104,14 @@ asmfunction!(__relibc_internal_sigentry: [" // Read first signal word mov eax, gs:[{tcb_sc_off} + {sc_word}] - mov edx, gs:[{tcb_sc_off} + {sc_word} + 4] - not edx - and eax, edx + and eax, gs:[{tcb_sc_off} + {sc_word} + 4] and eax, {SIGW0_PENDING_MASK} bsf eax, eax jnz 2f // Read second signal word mov eax, gs:[{tcb_sc_off} + {sc_word} + 8] - mov edx, gs:[{tcb_sc_off} + {sc_word} + 12] - not edx - and eax, edx + and eax, gs:[{tcb_sc_off} + {sc_word} + 12] and eax, {SIGW1_PENDING_MASK} bsf eax, eax jz 7f diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index a2cdf1adb5286e8576ed4ed6e22c7fae454941c0..8ae3b50f46d060b9c2eef347c16b66f5a0bc043a 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -136,7 +136,6 @@ asmfunction!(__relibc_internal_sigentry: [" mov rax, fs:[{tcb_sc_off} + {sc_word}] mov rdx, rax shr rdx, 32 - not edx and eax, edx and eax, {SIGW0_PENDING_MASK} bsf eax, eax @@ -146,7 +145,6 @@ asmfunction!(__relibc_internal_sigentry: [" mov rax, fs:[{tcb_sc_off} + {sc_word} + 8] mov rdx, rax shr rdx, 32 - not edx and eax, edx and eax, {SIGW1_PENDING_MASK} bsf eax, eax diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index e2beea9cef8cb793268ff347f903623ce5ba577c..63fcbd460e7b9adaf26a79814574d21621381b21 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -70,9 +70,9 @@ unsafe fn inner(stack: &mut SigStack) { SigactionKind::Handled { handler } => handler, }; - let mut sigmask_inside = sigaction.mask; + let mut sigallow_inside = !sigaction.mask; if !sigaction.flags.contains(SigactionFlags::NODEFER) { - sigmask_inside &= !sig_bit(stack.sig_num); + sigallow_inside &= !sig_bit(stack.sig_num); } let os = &Tcb::current().unwrap().os_specific; @@ -80,7 +80,7 @@ unsafe fn inner(stack: &mut SigStack) { // Set sigmask to sa_mask and unmark the signal as pending. let lo = os.control.word[0].load(Ordering::Relaxed) >> 32; let hi = os.control.word[1].load(Ordering::Relaxed) >> 32; - let prev_sigmask = lo | (hi << 32); + let prev_sigallow = lo | (hi << 32); let sig_group = stack.sig_num / 32; @@ -89,7 +89,7 @@ unsafe fn inner(stack: &mut SigStack) { if sig_group == 0 { prev &= !sig_bit(stack.sig_num); } - prev |= (sigmask_inside & 0xffff_ffff) << 32; + prev |= (sigallow_inside & 0xffff_ffff) << 32; Some(prev) }).unwrap(); let prev_w1 = os.control.word[1].fetch_update(Ordering::Relaxed, Ordering::Relaxed, |mut prev| { @@ -97,7 +97,7 @@ unsafe fn inner(stack: &mut SigStack) { if sig_group == 1 { prev &= !sig_bit(stack.sig_num); } - prev |= (sigmask_inside >> 32) << 32; + prev |= (sigallow_inside >> 32) << 32; Some(prev) }).unwrap(); @@ -119,7 +119,7 @@ unsafe fn inner(stack: &mut SigStack) { control_flags.store(control_flags.load(Ordering::Relaxed) | SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release); core::sync::atomic::compiler_fence(Ordering::Acquire); - // Update sigmask again. + // Update allowset again. let prev_w0 = os.control.word[0].fetch_update(Ordering::Relaxed, Ordering::Relaxed, |mut prev| { prev &= 0xffff_ffff; prev |= lo << 32; @@ -156,7 +156,7 @@ pub fn set_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { modify_sigmask(old, new.map(move |newmask| move |_, upper| if upper { newmask >> 32 } else { newmask } as u32)) } pub fn or_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { - // Parsing nightmare... + // Parsing nightmare... :) modify_sigmask(old, new.map(move |newmask| move |oldmask, upper| oldmask | if upper { newmask >> 32 } else { newmask } as u32)) } pub fn andn_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { @@ -169,7 +169,7 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32 let mut words = ctl.word.each_ref().map(|w| w.load(Ordering::Relaxed)); if let Some(old) = old { - *old = combine_mask(words); + *old = !combine_allowset(words); } let Some(mut op) = op else { return Ok(()); @@ -179,7 +179,11 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32 let mut cant_raise = 0; for i in 0..2 { - while let Err(changed) = ctl.word[i].compare_exchange(words[i], ((words[i] >> 32) << 32) | u64::from(op(words[i] as u32, i == 1)), Ordering::Relaxed, Ordering::Relaxed) { + let pending_bits = words[i] & 0xffff_ffff; + let allow_bits = (words[i] >> 32) as u32; + let new_allow_bits = !op(!allow_bits, i == 1); + + while let Err(changed) = ctl.word[i].compare_exchange(words[i], pending_bits | (u64::from(new_allow_bits) << 32), Ordering::Relaxed, Ordering::Relaxed) { // If kernel observed a signal being unblocked and pending simultaneously, it will have // set a flag causing it to check for the INHIBIT_SIGNALS flag every time the context // is switched to. To avoid race conditions, we should NOT auto-raise those signals in @@ -357,16 +361,14 @@ static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl { word: [ - AtomicU64::new(SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT), - AtomicU64::new(0), + //AtomicU64::new(SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | 0xffff_ffff_0000_0000), + AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" + AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" ], }; -fn expand_mask(mask: u64) -> [u64; 2] { - [mask & 0xffff_ffff, mask >> 32] -} -fn combine_mask([lo, hi]: [u64; 2]) -> u64 { - lo | ((hi & 0xffff_ffff) << 32) +fn combine_allowset([lo, hi]: [u64; 2]) -> u64 { + (lo >> 32) | ((hi >> 32) << 32) } const fn sig_bit(sig: usize) -> u64 { @@ -404,6 +406,9 @@ pub fn setup_sighandler(area: &RtSigarea) { .expect("failed to open thisproc:current/sighandler"); syscall::write(fd, &data).expect("failed to write to thisproc:current/sighandler"); let _ = syscall::close(fd); + + // TODO: Inherited set of ignored signals + set_sigmask(Some(0), None); } #[derive(Debug, Default)] pub struct RtSigarea { diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 32aaf675a5340ffcb8e1b8c33eadefe0d3380621..5dda2e77c167f6d5a868f2a6730ce9c86f09f9fb 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -305,8 +305,7 @@ pub fn execve( unreachable!() } else { - let mut sigprocmask = 0_u64; - redox_rt::signal::set_sigmask(None, Some(&mut sigprocmask)).unwrap(); + let sigprocmask = redox_rt::signal::get_sigmask().unwrap(); let extrainfo = ExtraInfo { cwd: Some(&cwd), diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index a5210a2a0daaf79c98fe3dda9d116c24d74596cf..f6751cb510c42e03e49b9ff0e8c2c272a4df7f12 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -136,13 +136,15 @@ pub(crate) unsafe fn create( ) -> Result<pthread_t, Errno> { let attrs = attrs.copied().unwrap_or_default(); - let mut procmask = 0_u64; + let mut current_sigmask = 0_u64; #[cfg(target_os = "redox")] - redox_rt::signal::set_sigmask(None, Some(&mut procmask)) - .expect("failed to obtain sigprocmask for caller"); + { + current_sigmask = redox_rt::signal::get_sigmask() + .expect("failed to obtain sigprocmask for caller"); + } // Create a locked mutex, unlocked by the thread after it has started. - let synchronization_mutex = Mutex::locked(procmask); + let synchronization_mutex = Mutex::locked(current_sigmask); let synchronization_mutex = &synchronization_mutex; let stack_size = attrs.stacksize.next_multiple_of(Sys::getpagesize()); @@ -248,8 +250,10 @@ unsafe extern "C" fn new_thread_shim( (&*mutex).manual_unlock(); #[cfg(target_os = "redox")] - redox_rt::signal::set_sigmask(Some(procmask), None) - .expect("failed to set procmask in child thread"); + { + redox_rt::signal::set_sigmask(Some(procmask), None) + .expect("failed to set procmask in child thread"); + } let retval = entry_point(arg);