Adapt to now-inverted signal mask (allowset).

This commit is contained in:
4lDO2
2024-06-26 12:58:27 +02:00
parent 157d9fb2ba
commit 2d66993b3f
5 changed files with 34 additions and 32 deletions
+2 -6
View File
@@ -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
-2
View File
@@ -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
+21 -16
View File
@@ -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 {
+1 -2
View File
@@ -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),
+10 -6
View File
@@ -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);