diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 8550bea91a5d6ef3d1693ad6d33c77f2bbb3d785..26d62a506eafa421b0e49893cff94dddf8759b33 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -89,3 +89,15 @@ asmfunction!(__relibc_internal_sigentry: [" mov x8, {SYS_SIGRETURN} svc 0 "] <= [inner = sym inner_c, SYS_SIGRETURN = const SYS_SIGRETURN]); + +asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" + # Load registers + ldp x8, x0, [sp], #16 + ldp x1, x2, [sp], #16 + ldp x3, x4, [sp], #16 + + # Call entry point + blr x8 + + ret +"]); diff --git a/redox-rt/src/arch/x86.rs b/redox-rt/src/arch/x86.rs index 56797839e9ccba554ef896a3139ed360b39cb548..eb33fc441afc9bfc7e40532352647f0273b22b64 100644 --- a/redox-rt/src/arch/x86.rs +++ b/redox-rt/src/arch/x86.rs @@ -101,3 +101,22 @@ asmfunction!(__relibc_internal_sigentry: [" mov eax, {SYS_SIGRETURN} int 0x80 "] <= [inner = sym inner_fastcall, SYS_SIGRETURN = const SYS_SIGRETURN]); + +asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" + # Load registers + pop eax + + sub esp, 8 + + mov DWORD PTR [esp], 0x00001F80 + # TODO: ldmxcsr [esp] + mov WORD PTR [esp], 0x037F + fldcw [esp] + + add esp, 8 + + # Call entry point + call eax + + ret +"] <= []); diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 542b751d2679c8c56bce761239b5731019559e60..2d9fb84be4cd2bbeb0ae2d2352427ba0663fde82 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -1,4 +1,3 @@ -use syscall::number::SYS_SIGRETURN; use syscall::error::*; use crate::proc::{fork_inner, FdGuard}; @@ -103,9 +102,9 @@ asmfunction!(__relibc_internal_sigentry_fxsave: [" fxrstor64 [rsp] add rsp, 4096 - mov eax, {SYS_SIGRETURN} + //mov eax, {{SYS_SIGRETURN}} syscall -"] <= [inner = sym inner_c, SYS_SIGRETURN = const SYS_SIGRETURN]); +"] <= [inner = sym inner_c]); asmfunction!(__relibc_internal_sigentry_xsave: [" sub rsp, 4096 @@ -127,6 +126,31 @@ asmfunction!(__relibc_internal_sigentry_xsave: [" xrstor [rsp] add rsp, 4096 - mov eax, {SYS_SIGRETURN} + //mov eax, {{SYS_SIGRETURN}} syscall -"] <= [inner = sym inner_c, SYS_SIGRETURN = const SYS_SIGRETURN]); +"] <= [inner = sym inner_c]); + +asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" + # Load registers + pop rax + pop rdi + pop rsi + pop rdx + pop rcx + pop r8 + pop r9 + + sub rsp, 8 + + mov DWORD PTR [rsp], 0x00001F80 + ldmxcsr [rsp] + mov WORD PTR [rsp], 0x037F + fldcw [rsp] + + add rsp, 8 + + # Call entry point + call rax + + ret +"] <= []); diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 421695e13f2c4c3c24d34c3efec0655ec7ffd4c6..7ec7ca9d3b397be5b795c2c525e6a44288f1fe41 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(asm_const, array_chunks, int_roundings, let_chains, slice_ptr_get)] +#![feature(asm_const, array_chunks, int_roundings, let_chains, slice_ptr_get, sync_unsafe_cell, thread_local)] #![forbid(unreachable_patterns)] extern crate alloc; @@ -31,3 +31,4 @@ pub mod proc; pub mod auxv_defs; pub mod signal; +pub mod thread; diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index a01200fc2bfb2b1da3c35c8c7948508619c82066..fcf2a5c30996f0f56cc2d3f9594fb96fc993fbab 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -710,11 +710,11 @@ pub fn create_set_addr_space_buf( /// descriptors are reobtained through `fmap`. Other mappings are kept but duplicated using CoW. pub fn fork_impl() -> Result<usize> { let mut old_mask = 0_u64; - syscall::sigprocmask(syscall::SIG_SETMASK, None, Some(&mut old_mask))?; + crate::signal::set_sigmask(None, Some(&mut old_mask))?; let pid = unsafe { Error::demux(__relibc_internal_fork_wrapper())? }; if pid == 0 { - syscall::sigprocmask(syscall::SIG_SETMASK, Some(&old_mask), None)?; + crate::signal::set_sigmask(Some(old_mask), None)?; } Ok(pid) } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 19932ec8c2a98fc9ef44de6704c147a96afc8792..4247f81702587ec37bbed6c2ae92f94bf473de6f 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -1,5 +1,8 @@ +use core::cell::Cell; use core::ffi::c_int; +use syscall::{Result, Sigcontrol}; + use crate::arch::*; #[cfg(target_arch = "x86_64")] @@ -21,11 +24,7 @@ pub fn sighandler_function() -> usize { } } -pub fn setup_sighandler() { - // TODO - let altstack_base = 0_usize; - let altstack_len = 0_usize; - +pub fn setup_sighandler(control: &Sigcontrol) { #[cfg(target_arch = "x86_64")] { let cpuid_eax1_ecx = unsafe { core::arch::x86_64::__cpuid(1) }.ecx; @@ -33,9 +32,9 @@ pub fn setup_sighandler() { } let data = syscall::SetSighandlerData { - entry: sighandler_function(), - altstack_base, - altstack_len, + user_handler: sighandler_function(), + excp_handler: 0, // TODO + word_addr: control as *const Sigcontrol as usize, }; let fd = syscall::open( @@ -55,13 +54,14 @@ pub struct SigStack { #[cfg(target_arch = "x86")] fx: [u8; 512], - kernel_pushed: syscall::SignalStack, + sa_handler: usize, + sig_num: usize, } #[inline(always)] unsafe fn inner(stack: &mut SigStack) { - let handler: extern "C" fn(c_int) = core::mem::transmute(stack.kernel_pushed.sa_handler); - handler(stack.kernel_pushed.sig_num as c_int) + let handler: extern "C" fn(c_int) = core::mem::transmute(stack.sa_handler); + handler(stack.sig_num as c_int) } #[cfg(not(target_arch = "x86"))] pub(crate) unsafe extern "C" fn inner_c(stack: usize) { @@ -71,3 +71,46 @@ pub(crate) unsafe extern "C" fn inner_c(stack: usize) { unsafe extern "fastcall" fn inner_fastcall(stack: usize) { inner(&mut *(stack as *mut SigStack)) } + +pub fn set_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { + todo!() +} +pub fn or_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { + todo!() +} +pub fn andn_sigmask(new: Option<u64>, old: Option<&mut u64>) -> Result<()> { + todo!() +} + +extern "C" { + pub fn __relibc_internal_get_sigcontrol_addr() -> &'static Sigcontrol; +} + +pub struct TmpDisableSignalsGuard { _inner: () } + +#[thread_local] +static TMP_DISABLE_SIGNALS_DEPTH: Cell<u64> = Cell::new(0); + +pub fn tmp_disable_signals() -> TmpDisableSignalsGuard { + unsafe { + let ctl = __relibc_internal_get_sigcontrol_addr().control_flags.get(); + ctl.write_volatile(ctl.read_volatile() | syscall::flag::INHIBIT_DELIVERY); + // TODO: fence? + TMP_DISABLE_SIGNALS_DEPTH.set(TMP_DISABLE_SIGNALS_DEPTH.get() + 1); + } + + TmpDisableSignalsGuard { _inner: () } +} +impl Drop for TmpDisableSignalsGuard { + fn drop(&mut self) { + unsafe { + let old = TMP_DISABLE_SIGNALS_DEPTH.get(); + TMP_DISABLE_SIGNALS_DEPTH.set(old - 1); + + if old == 1 { + let ctl = __relibc_internal_get_sigcontrol_addr().control_flags.get(); + ctl.write_volatile(ctl.read_volatile() & !syscall::flag::INHIBIT_DELIVERY); + } + } + } +} diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs new file mode 100644 index 0000000000000000000000000000000000000000..298858315fbaa55c80beeb5503b3f8aa5badcc49 --- /dev/null +++ b/redox-rt/src/thread.rs @@ -0,0 +1,72 @@ +use syscall::SetSighandlerData; +use syscall::{Result, O_CLOEXEC}; + +use crate::arch::*; +use crate::proc::*; +use crate::signal::sighandler_function; + +/// Spawns a new context sharing the same address space as the current one (i.e. a new thread). +pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> { + let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?); + let (new_pid_fd, new_pid) = new_context()?; + + copy_str(*cur_pid_fd, *new_pid_fd, "name")?; + + // Inherit existing address space + { + let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); + let new_addr_space_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?); + + let buf = create_set_addr_space_buf( + *cur_addr_space_fd, + __relibc_internal_rlct_clone_ret() as usize, + stack as usize, + ); + let _ = syscall::write(*new_addr_space_sel_fd, &buf)?; + } + + // Inherit file table + { + let cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?); + let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?); + + let _ = syscall::write( + *new_filetable_sel_fd, + &usize::to_ne_bytes(*cur_filetable_fd), + )?; + } + + // Inherit sigactions (on Linux, CLONE_THREAD requires CLONE_SIGHAND which implies the sigactions + // table is reused). + { + let cur_sigaction_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"sigactions")?); + let new_sigaction_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-sigactions")?); + + let _ = syscall::write( + *new_sigaction_sel_fd, + &usize::to_ne_bytes(*cur_sigaction_fd), + )?; + } + // Inherit sighandler, but not the sigaltstack. + { + let new_sighandler_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"sighandler")?); + let data = SetSighandlerData { + user_handler: sighandler_function(), + excp_handler: 0, + word_addr: 0, // TODO + }; + let _ = syscall::write(*new_sighandler_fd, &data)?; + } + + // Sigprocmask starts as "block all", and is initialized when the thread has actually returned + // from clone_ret. + + // TODO: Should some of these registers be inherited? + //copy_env_regs(*cur_pid_fd, *new_pid_fd)?; + + // Unblock context. + let start_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"start")?); + let _ = syscall::write(*start_fd, &[0])?; + + Ok(new_pid) +} diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 5e8d52063aceb72e569d64a1562031b5b4746b4b..9c924c1d217d785c0269ab600b7e7ce7084519aa 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -7,7 +7,7 @@ use cbitset::BitSet; use crate::{ header::{errno, time::timespec}, platform::{self, types::*, Pal, PalSignal, Sys}, - pthread, + pthread::{self, ResultExt}, }; pub use self::sys::*; @@ -107,13 +107,7 @@ pub unsafe extern "C" fn sigaction( act: *const sigaction, oact: *mut sigaction, ) -> c_int { - let act_opt = act.as_ref().map(|act| { - let mut act_clone = act.clone(); - act_clone.sa_flags |= SA_RESTORER as c_ulong; - act_clone.sa_restorer = Some(__restore_rt); - act_clone - }); - Sys::sigaction(sig, act_opt.as_ref(), oact.as_mut()) + Sys::sigaction(sig, act.as_ref(), oact.as_mut()).map(|()| 0).or_minus_one_errno() } #[no_mangle] @@ -270,14 +264,22 @@ pub unsafe extern "C" fn sigprocmask( set: *const sigset_t, oset: *mut sigset_t, ) -> c_int { - let set = set.as_ref().map(|&block| block & !RLCT_SIGNAL_MASK); - - Sys::sigprocmask( - how, - set.as_ref() - .map_or(core::ptr::null(), |r| r as *const sigset_t), - oset, - ) + (|| { + let set = set.as_ref().map(|&block| block & !RLCT_SIGNAL_MASK); + let mut oset = oset.as_mut(); + + Sys::sigprocmask( + how, + set.as_ref(), + oset.as_deref_mut(), // as_deref_mut for lifetime reasons + )?; + + if let Some(oset) = oset { + *oset &= !RLCT_SIGNAL_MASK; + } + + Ok(0) + })().or_minus_one_errno() } #[no_mangle] diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index fd3ac90bb27913b580339dd57476e3595327978a..2b012ea7fd1a13ff7a83ce3db48419b18137260a 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -1,4 +1,5 @@ use alloc::vec::Vec; +use syscall::Sigcontrol; use core::{arch::asm, cell::UnsafeCell, mem, ptr, slice, sync::atomic::AtomicBool}; use goblin::error::{Error, Result}; @@ -53,6 +54,8 @@ pub struct Tcb { pub mspace: *const Mutex<Dlmalloc>, /// Underlying pthread_t struct, pthread_self() returns &self.pthread pub pthread: Pthread, + #[cfg(target_os = "redox")] + pub sigcontrol: Sigcontrol, } impl Tcb { @@ -84,6 +87,8 @@ impl Tcb { stack_size: 0, os_tid: UnsafeCell::new(OsTid::default()), }, + #[cfg(target_os = "redox")] + sigcontrol: Default::default(), }, ); diff --git a/src/platform/mod.rs b/src/platform/mod.rs index f523842108253b0d2987d4d9dc971a444ddf914d..9b598d68a02d34e628a7572016e5037b166b6b78 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -306,7 +306,7 @@ pub fn init(auxvs: Box<[[usize; 2]]>) { if let Some(mask) = get_auxv(&auxvs, AT_REDOX_INHERITED_SIGPROCMASK_HI) { inherited_sigprocmask |= (mask as u64) << 32; } - syscall::sigprocmask(syscall::SIG_SETMASK, Some(&inherited_sigprocmask), None).unwrap(); + redox_rt::signal::set_sigmask(Some(inherited_sigprocmask), None).unwrap(); } #[cfg(not(target_os = "redox"))] pub fn init(auxvs: Box<[[usize; 2]]>) {} diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs index c085c678e8e7b025ec217307e921d5ec766a15fc..eeb5031a76394887f7350a1b3ebbd6a91d190c0a 100644 --- a/src/platform/pal/signal.rs +++ b/src/platform/pal/signal.rs @@ -1,9 +1,9 @@ use super::super::{types::*, Pal}; -use crate::header::{ +use crate::{header::{ signal::{sigaction, siginfo_t, sigset_t, stack_t}, sys_time::itimerval, time::timespec, -}; +}, pthread::Errno}; pub trait PalSignal: Pal { unsafe fn getitimer(which: c_int, out: *mut itimerval) -> c_int; @@ -16,13 +16,13 @@ pub trait PalSignal: Pal { unsafe fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int; - fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> c_int; + fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> Result<(), Errno>; unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int; unsafe fn sigpending(set: *mut sigset_t) -> c_int; - unsafe fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int; + fn sigprocmask(how: c_int, set: Option<&sigset_t>, oset: Option<&mut sigset_t>) -> Result<(), Errno>; unsafe fn sigsuspend(set: *const sigset_t) -> c_int; diff --git a/src/platform/redox/clone.rs b/src/platform/redox/clone.rs index 5ec6f7785addbede99b27126b8814ee4e42424bd..017696ce6b15869d626c9cef28aa2400a5f3ffd6 100644 --- a/src/platform/redox/clone.rs +++ b/src/platform/redox/clone.rs @@ -32,153 +32,4 @@ pub fn wrlock() -> impl Drop { Guard } - -/// Spawns a new context sharing the same address space as the current one (i.e. a new thread). -pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result<usize> { - let cur_pid_fd = FdGuard::new(syscall::open("thisproc:current/open_via_dup", O_CLOEXEC)?); - let (new_pid_fd, new_pid) = new_context()?; - - copy_str(*cur_pid_fd, *new_pid_fd, "name")?; - - // Inherit existing address space - { - let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); - let new_addr_space_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?); - - let buf = create_set_addr_space_buf( - *cur_addr_space_fd, - __relibc_internal_rlct_clone_ret as usize, - stack as usize, - ); - let _ = syscall::write(*new_addr_space_sel_fd, &buf)?; - } - - // Inherit file table - { - let cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?); - let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?); - - let _ = syscall::write( - *new_filetable_sel_fd, - &usize::to_ne_bytes(*cur_filetable_fd), - )?; - } - - // Inherit sigactions (on Linux, CLONE_THREAD requires CLONE_SIGHAND which implies the sigactions - // table is reused). - { - let cur_sigaction_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"sigactions")?); - let new_sigaction_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-sigactions")?); - - let _ = syscall::write( - *new_sigaction_sel_fd, - &usize::to_ne_bytes(*cur_sigaction_fd), - )?; - } - // Inherit sighandler, but not the sigaltstack. - { - let new_sighandler_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"sighandler")?); - let data = SetSighandlerData { - entry: sighandler_function(), - altstack_base: 0, - altstack_len: 0, - }; - let _ = syscall::write(*new_sighandler_fd, &data)?; - } - - // Sigprocmask starts as "block all", and is initialized when the thread has actually returned - // from clone_ret. - - // TODO: Should some of these registers be inherited? - //copy_env_regs(*cur_pid_fd, *new_pid_fd)?; - - // Unblock context. - let start_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"start")?); - let _ = syscall::write(*start_fd, &[0])?; - - Ok(new_pid) -} - -extern "C" { - fn __relibc_internal_rlct_clone_ret(); -} - -#[cfg(target_arch = "aarch64")] -core::arch::global_asm!( - " - .globl __relibc_internal_rlct_clone_ret - .type __relibc_internal_rlct_clone_ret, @function - .p2align 6 -__relibc_internal_rlct_clone_ret: - # Load registers - ldp x8, x0, [sp], #16 - ldp x1, x2, [sp], #16 - ldp x3, x4, [sp], #16 - - # Call entry point - blr x8 - - ret - .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret -" -); - -#[cfg(target_arch = "x86")] -core::arch::global_asm!( - " - .globl __relibc_internal_rlct_clone_ret - .type __relibc_internal_rlct_clone_ret, @function - .p2align 6 -__relibc_internal_rlct_clone_ret: - # Load registers - pop eax - - sub esp, 8 - - mov DWORD PTR [esp], 0x00001F80 - # TODO: ldmxcsr [esp] - mov WORD PTR [esp], 0x037F - fldcw [esp] - - add esp, 8 - - # Call entry point - call eax - - ret - .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret -" -); - -#[cfg(target_arch = "x86_64")] -core::arch::global_asm!( - " - .globl __relibc_internal_rlct_clone_ret - .type __relibc_internal_rlct_clone_ret, @function - .p2align 6 -__relibc_internal_rlct_clone_ret: - # Load registers - pop rax - pop rdi - pop rsi - pop rdx - pop rcx - pop r8 - pop r9 - - sub rsp, 8 - - mov DWORD PTR [rsp], 0x00001F80 - ldmxcsr [rsp] - mov WORD PTR [rsp], 0x037F - fldcw [rsp] - - add rsp, 8 - - # Call entry point - call rax - - ret - .size __relibc_internal_rlct_clone_ret, . - __relibc_internal_rlct_clone_ret -" -); +pub use redox_rt::thread::*; diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 56f3093a408dec3410d8605c93c18bdb17231f26..32aaf675a5340ffcb8e1b8c33eadefe0d3380621 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -306,7 +306,7 @@ pub fn execve( unreachable!() } else { let mut sigprocmask = 0_u64; - syscall::sigprocmask(syscall::SIG_SETMASK, None, Some(&mut sigprocmask)).unwrap(); + redox_rt::signal::set_sigmask(None, Some(&mut sigprocmask)).unwrap(); let extrainfo = ExtraInfo { cwd: Some(&cwd), diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 15ea59a7ed305b45c4c1693605417aa76dc08bc9..9ceed89a715912d69c77234bd3e0672908b4b34b 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -4,7 +4,7 @@ use syscall::{Error, Result, WaitFlags, EMFILE}; use crate::{ header::{ - errno::EINVAL, signal::sigaction, sys_stat::UTIME_NOW, sys_uio::iovec, time::timespec, + errno::EINVAL, signal::{sigaction, SIG_SETMASK}, sys_stat::UTIME_NOW, sys_uio::iovec, time::timespec, }, platform::types::*, }; @@ -249,7 +249,7 @@ pub unsafe extern "C" fn redox_sigaction_v1( new: *const sigaction, old: *mut sigaction, ) -> RawResult { - Error::mux(super::signal::sigaction_impl(signal as i32, new.as_ref(), old.as_mut()).map(|()| 0)) + todo!() } #[no_mangle] @@ -258,7 +258,7 @@ pub unsafe extern "C" fn redox_sigprocmask_v1( new: *const u64, old: *mut u64, ) -> RawResult { - Error::mux(super::signal::sigprocmask_impl(how as i32, new, old).map(|()| 0)) + todo!() } #[no_mangle] pub unsafe extern "C" fn redox_mmap_v1( diff --git a/src/platform/redox/path.rs b/src/platform/redox/path.rs index bdcb4a42546ce75a14c7a982f390d4864221e3ab..01c075748bad8c5e92fb1a51cb2aaa04e892a2e0 100644 --- a/src/platform/redox/path.rs +++ b/src/platform/redox/path.rs @@ -1,4 +1,5 @@ use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec}; +use redox_rt::signal::tmp_disable_signals; use syscall::{data::Stat, error::*, flag::*}; use super::{libcscheme, FdGuard}; @@ -19,7 +20,7 @@ const PATH_MAX: usize = 4096; // and after acquiring the locks. (TODO: ArcSwap? That will need to be ported to no_std first, // though). pub fn chdir(path: &str) -> Result<()> { - let _siglock = SignalMask::lock(); + let _siglock = tmp_disable_signals(); let mut cwd_guard = CWD.lock(); let canonicalized = @@ -40,13 +41,13 @@ pub fn chdir(path: &str) -> Result<()> { } pub fn clone_cwd() -> Option<Box<str>> { - let _siglock = SignalMask::lock(); + let _siglock = tmp_disable_signals(); CWD.lock().clone() } // TODO: MaybeUninit pub fn getcwd(buf: &mut [u8]) -> Option<usize> { - let _siglock = SignalMask::lock(); + let _siglock = tmp_disable_signals(); let cwd_guard = CWD.lock(); let cwd = cwd_guard.as_deref().unwrap_or("").as_bytes(); @@ -61,9 +62,8 @@ pub fn getcwd(buf: &mut [u8]) -> Option<usize> { Some(cwd.len()) } -// TODO: Move cwd from kernel to libc. It is passed via auxiliary vectors. pub fn canonicalize(path: &str) -> Result<String> { - let _siglock = SignalMask::lock(); + let _siglock = tmp_disable_signals(); let cwd = CWD.lock(); canonicalize_using_cwd(cwd.as_deref(), path).ok_or(Error::new(ENOENT)) } @@ -72,29 +72,10 @@ pub fn canonicalize(path: &str) -> Result<String> { static CWD: Mutex<Option<Box<str>>> = Mutex::new(None); pub fn setcwd_manual(cwd: Box<str>) { - let _siglock = SignalMask::lock(); + let _siglock = tmp_disable_signals(); *CWD.lock() = Some(cwd); } -/// RAII guard able to magically fix signal unsafety, by disabling signals during a critical -/// section. -pub struct SignalMask { - oldset: u64, -} -impl SignalMask { - pub fn lock() -> Self { - let mut oldset = 0; - syscall::sigprocmask(syscall::SIG_SETMASK, Some(&!0), Some(&mut oldset)) - .expect("failed to run sigprocmask"); - Self { oldset } - } -} -impl Drop for SignalMask { - fn drop(&mut self) { - let _ = syscall::sigprocmask(syscall::SIG_SETMASK, Some(&self.oldset), None); - } -} - pub fn open(path: &str, flags: usize) -> Result<usize> { // TODO: SYMLOOP_MAX const MAX_LEVEL: usize = 64; diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 3fa3c81e3c8b25f066da0767f325b6b1cc5b6f67..f8f82a8d88a52771c65d0ce89a9069b292cf1fe7 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -1,5 +1,5 @@ use core::mem; -use syscall::{self, number::SYS_SIGRETURN, Result, SetSighandlerData, SignalStack}; +use syscall::{self, Result}; use super::{ super::{types::*, Pal, PalSignal}, @@ -8,11 +8,11 @@ use super::{ use crate::{ header::{ errno::{EINVAL, ENOSYS}, - signal::{sigaction, siginfo_t, sigset_t, stack_t}, + signal::{sigaction, siginfo_t, sigset_t, stack_t, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK}, sys_time::{itimerval, ITIMER_REAL}, time::timespec, }, - platform::ERRNO, + platform::ERRNO, pthread::Errno, }; impl PalSignal for Sys { @@ -104,8 +104,8 @@ impl PalSignal for Sys { 0 } - fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> c_int { - e(sigaction_impl(sig, act, oact).map(|()| 0)) as c_int + fn sigaction(sig: c_int, act: Option<&sigaction>, oact: Option<&mut sigaction>) -> Result<(), Errno> { + todo!() } unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int { @@ -117,8 +117,14 @@ impl PalSignal for Sys { -1 } - unsafe fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int { - e(sigprocmask_impl(how, set, oset).map(|()| 0)) as c_int + fn sigprocmask(how: c_int, set: Option<&sigset_t>, oset: Option<&mut sigset_t>) -> Result<(), Errno> { + Ok(match how { + SIG_SETMASK => redox_rt::signal::set_sigmask(set.copied(), oset)?, + SIG_BLOCK => redox_rt::signal::or_sigmask(set.copied(), oset)?, + SIG_UNBLOCK => redox_rt::signal::andn_sigmask(set.copied(), oset)?, + + _ => return Err(Errno(EINVAL)), + }) } unsafe fn sigsuspend(set: *const sigset_t) -> c_int { @@ -135,34 +141,3 @@ impl PalSignal for Sys { -1 } } -pub(crate) fn sigaction_impl( - sig: i32, - act: Option<&sigaction>, - oact: Option<&mut sigaction>, -) -> Result<()> { - let new_opt = act.map(|act| { - let sa_handler = unsafe { mem::transmute(act.sa_handler) }; - syscall::SigAction { - sa_handler, - sa_mask: act.sa_mask as u64, - sa_flags: syscall::SigActionFlags::from_bits(act.sa_flags as usize) - .expect("sigaction: invalid bit pattern"), - } - }); - let mut old_opt = oact.as_ref().map(|_| syscall::SigAction::default()); - syscall::sigaction(sig as usize, new_opt.as_ref(), old_opt.as_mut())?; - if let (Some(old), Some(oact)) = (old_opt, oact) { - oact.sa_handler = unsafe { mem::transmute(old.sa_handler) }; - oact.sa_mask = old.sa_mask as sigset_t; - oact.sa_flags = old.sa_flags.bits() as c_ulong; - } - Ok(()) -} -pub(crate) unsafe fn sigprocmask_impl( - how: i32, - set: *const sigset_t, - oset: *mut sigset_t, -) -> Result<()> { - syscall::sigprocmask(how as usize, set.as_ref(), oset.as_mut())?; - Ok(()) -} diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index 37402d45136d4d1eca44100e661ee2dab0d69f2e..0290f26fbc528924803c813d5de062bebc66f1f5 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -132,7 +132,7 @@ pub(crate) unsafe fn create( let mut procmask = 0_u64; #[cfg(target_os = "redox")] - syscall::sigprocmask(syscall::SIG_SETMASK, None, Some(&mut procmask)) + redox_rt::signal::set_sigmask(None, Some(&mut procmask)) .expect("failed to obtain sigprocmask for caller"); // Create a locked mutex, unlocked by the thread after it has started. @@ -242,7 +242,7 @@ unsafe extern "C" fn new_thread_shim( (&*mutex).manual_unlock(); #[cfg(target_os = "redox")] - syscall::sigprocmask(syscall::SIG_SETMASK, Some(&procmask), None) + redox_rt::signal::set_sigmask(Some(procmask), None) .expect("failed to set procmask in child thread"); let retval = entry_point(arg); diff --git a/src/start.rs b/src/start.rs index dc0e3e26e58c8e8c43167dc1457a55521c164f0d..540ddb6d12cae536a45111660e204d0694e4b5dc 100644 --- a/src/start.rs +++ b/src/start.rs @@ -3,7 +3,7 @@ use core::{intrinsics, ptr}; use crate::{ header::{libgen, stdio, stdlib}, - ld_so::{self, linker::Linker}, + ld_so::{self, linker::Linker, tcb::Tcb}, platform::{self, get_auxvs, types::*, Pal, Sys}, sync::mutex::Mutex, ALLOCATOR, @@ -157,6 +157,8 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { //TODO: load root object tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker))); } + #[cfg(target_os = "redox")] + redox_rt::signal::setup_sighandler(&tcb.sigcontrol); } // Set up argc and argv @@ -182,8 +184,6 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { platform::OUR_ENVIRON = copy_string_array(envp, len); platform::environ = platform::OUR_ENVIRON.as_mut_ptr(); } - #[cfg(target_os = "redox")] - redox_rt::signal::setup_sighandler(); let auxvs = get_auxvs(sp.auxv().cast()); crate::platform::init(auxvs);