Fix sigtimedwait realtime signals, almost handler too.

This commit is contained in:
4lDO2
2025-04-13 20:55:35 +02:00
parent 6d72048b13
commit f813f5a222
6 changed files with 87 additions and 32 deletions
+35 -10
View File
@@ -7,11 +7,11 @@ use core::{
use syscall::{
data::{SigProcControl, Sigcontrol},
error::*,
RtSigInfo,
};
use crate::{
proc::{fork_inner, FdGuard, ForkArgs},
protocol::{ProcCall, RtSigInfo},
signal::{get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT},
Tcb,
};
@@ -29,6 +29,9 @@ pub struct SigArea {
pub tmp_rdx: usize,
pub tmp_rdi: usize,
pub tmp_rsi: usize,
pub tmp_r8: usize,
pub tmp_r10: usize,
pub tmp_r12: usize,
pub tmp_rt_inf: RtSigInfo,
pub tmp_id_inf: u64,
@@ -37,6 +40,7 @@ pub struct SigArea {
pub disable_signals_depth: u64,
pub last_sig_was_restart: bool,
pub last_sigstack: Option<NonNull<SigStack>>,
pub proc_fd: usize, // TODO: use global variable instead, fix linker errors
}
#[repr(C, align(16))]
@@ -188,6 +192,9 @@ asmfunction!(__relibc_internal_sigentry: ["
mov fs:[{tcb_sa_off} + {sa_tmp_rdx}], rdx
mov fs:[{tcb_sa_off} + {sa_tmp_rdi}], rdi
mov fs:[{tcb_sa_off} + {sa_tmp_rsi}], rsi
mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r8
mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r10
mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r12
// First, select signal, always pick first available bit
1:
@@ -225,14 +232,24 @@ asmfunction!(__relibc_internal_sigentry: ["
jc 2f // if so, continue as usual
// otherwise, try (competitively) dequeueing realtime signal
mov esi, eax
mov eax, {SYS_SIGDEQUEUE}
mov rdi, fs:[0]
add rdi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig
// SYS_CALL(fd, payload_base, payload_len, metadata_base, metadata_len | (flags << 8))
// rax rdi rsi rdx r10 r8
mov r12d, eax
mov rsi, fs:[0]
mov rdi, [rsi+{tcb_sa_off}+{sa_proc_fd}]
add rsi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig
mov rdx, {RTINF_SIZE}
mov [rsi], eax
lea r10, [rip + {proc_call_sigdeq}]
mov r8, 1
mov eax, {SYS_CALL}
syscall
ud2
test eax, eax
jnz 1b // assumes error can only be EAGAIN
lea eax, [esi + 32]
lea eax, [r12d + 32]
jmp 9f
2:
mov edx, eax
@@ -285,13 +302,13 @@ asmfunction!(__relibc_internal_sigentry: ["
push fs:[{tcb_sa_off} + {sa_tmp_rdx}]
push rcx
push fs:[{tcb_sa_off} + {sa_tmp_rax}]
push r8
push fs:[{tcb_sa_off} + {sa_tmp_r8}]
push r9
push r10
push fs:[{tcb_sa_off} + {sa_tmp_r10}]
push r11
push rbx
push rbp
push r12
push fs:[{tcb_sa_off} + {sa_tmp_r12}]
push r13
push r14
push r15
@@ -418,10 +435,14 @@ __relibc_internal_sigentry_crit_third:
sa_tmp_rdx = const offset_of!(SigArea, tmp_rdx),
sa_tmp_rdi = const offset_of!(SigArea, tmp_rdi),
sa_tmp_rsi = const offset_of!(SigArea, tmp_rsi),
sa_tmp_r8 = const offset_of!(SigArea, tmp_r8),
sa_tmp_r10 = const offset_of!(SigArea, tmp_r10),
sa_tmp_r12 = const offset_of!(SigArea, tmp_r12),
sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf),
sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf),
sa_altstack_top = const offset_of!(SigArea, altstack_top),
sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
sa_proc_fd = const offset_of!(SigArea, proc_fd),
sc_saved_rflags = const offset_of!(Sigcontrol, saved_archdep_reg),
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
sc_word = const offset_of!(Sigcontrol, word),
@@ -437,7 +458,9 @@ __relibc_internal_sigentry_crit_third:
REDZONE_SIZE = const 128,
STACK_ALIGN = const 16,
SA_ONSTACK_BIT = const 58, // (1 << 58) >> 32 = 0x0400_0000
SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE,
SYS_CALL = const syscall::SYS_CALL,
proc_call_sigdeq = sym PROC_CALL_SIGDEQ,
RTINF_SIZE = const size_of::<RtSigInfo>(),
]);
extern "C" {
@@ -503,3 +526,5 @@ pub fn current_sp() -> usize {
}
sp
}
static PROC_CALL_SIGDEQ: u64 = ProcCall::Sigdeq as u64;
+5 -7
View File
@@ -17,7 +17,11 @@ use core::{
use generic_rt::{ExpectTlsFree, GenericTcb};
use syscall::Sigcontrol;
use self::{proc::FdGuard, protocol::ProcMeta, sync::Mutex};
use self::{
proc::{FdGuard, STATIC_PROC_INFO},
protocol::ProcMeta,
sync::Mutex,
};
extern crate alloc;
@@ -235,12 +239,6 @@ struct DynamicProcInfo {
sgid: u32,
}
static STATIC_PROC_INFO: SyncUnsafeCell<StaticProcInfo> = SyncUnsafeCell::new(StaticProcInfo {
pid: 0,
ppid: 0,
proc_fd: MaybeUninit::uninit(),
has_proc_fd: false,
});
static DYNAMIC_PROC_INFO: Mutex<DynamicProcInfo> = Mutex::new(DynamicProcInfo {
pgid: u32::MAX,
ruid: u32::MAX,
+9 -1
View File
@@ -1,4 +1,5 @@
use core::{
cell::SyncUnsafeCell,
fmt::Debug,
mem::{size_of, MaybeUninit},
};
@@ -9,7 +10,7 @@ use crate::{
protocol::{ProcCall, ThreadCall},
read_proc_meta, static_proc_info,
sys::{proc_call, thread_call},
RtTcb, DYNAMIC_PROC_INFO, STATIC_PROC_INFO,
RtTcb, StaticProcInfo, DYNAMIC_PROC_INFO,
};
use alloc::{boxed::Box, collections::BTreeMap, vec};
@@ -983,3 +984,10 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] {
managed_thr_fd,
]
}
pub(crate) static STATIC_PROC_INFO: SyncUnsafeCell<StaticProcInfo> =
SyncUnsafeCell::new(StaticProcInfo {
pid: 0,
ppid: 0,
proc_fd: MaybeUninit::zeroed(),
has_proc_fd: false,
});
+11
View File
@@ -33,6 +33,7 @@ pub enum ProcCall {
// TODO: replace with sendfd equivalent syscall for sending memory
SyncSigPctl = 10,
Sigdeq = 11,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(usize)]
@@ -57,6 +58,7 @@ impl ProcCall {
8 => Self::Kill,
9 => Self::Sigq,
10 => Self::SyncSigPctl,
11 => Self::Sigdeq,
_ => return None,
})
}
@@ -147,3 +149,12 @@ impl ProcKillTarget {
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct RtSigInfo {
pub arg: usize,
pub code: i32,
pub uid: u32,
pub pid: u32, // TODO: usize?
}
unsafe impl plain::Plain for RtSigInfo {}
+23 -10
View File
@@ -1,13 +1,19 @@
use core::{ffi::c_int, mem::MaybeUninit, ptr::NonNull, sync::atomic::Ordering};
use core::{ffi::c_int, ptr::NonNull, sync::atomic::Ordering};
use syscall::{
data::AtomicU64, CallFlags, Error, RawAction, Result, RtSigInfo, SenderInfo, SetSighandlerData,
data::AtomicU64, CallFlags, Error, RawAction, Result, SenderInfo, SetSighandlerData,
SigProcControl, Sigcontrol, SigcontrolFlags, TimeSpec, EAGAIN, EINTR, EINVAL, ENOMEM, EPERM,
SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH,
};
use crate::{
arch::*, proc::FdGuard, protocol::ThreadCall, sync::Mutex, sys::this_thread_call, RtTcb, Tcb,
arch::*,
proc::FdGuard,
protocol::{ProcCall, RtSigInfo, ThreadCall},
static_proc_info,
sync::Mutex,
sys::{proc_call, this_thread_call},
RtTcb, Tcb,
};
#[cfg(target_arch = "x86_64")]
@@ -558,6 +564,11 @@ pub fn setup_sighandler(tcb: &RtTcb) {
// equivalent to not using any altstack at all (the default).
arch.altstack_top = usize::MAX;
arch.altstack_bottom = 0;
/*#[cfg(target_arch = "x86_64")]
unsafe {
assert!(static_proc_info().has_proc_fd);
arch.proc_fd = **static_proc_info().proc_fd.assume_init_ref();
}*/
// TODO
#[cfg(any(target_arch = "x86", target_arch = "aarch64", target_arch = "riscv64"))]
{
@@ -774,15 +785,17 @@ fn try_claim_single(sig_idx: u32, thread_control: Option<&Sigcontrol>) -> Option
if sig_group == 1 && thread_control.is_none() {
// Queued (realtime) signal
let mut ret = MaybeUninit::<RtSigInfo>::uninit();
let rt_inf = unsafe {
syscall::syscall2(
syscall::SYS_SIGDEQUEUE,
ret.as_mut_ptr() as usize,
sig_idx as usize - 32,
let rt_inf: RtSigInfo = unsafe {
let mut buf = [0_u8; size_of::<RtSigInfo>()];
buf[..4].copy_from_slice(&(sig_idx - 32).to_ne_bytes());
proc_call(
**static_proc_info().proc_fd.assume_init_ref(),
&mut buf,
CallFlags::empty(),
&[ProcCall::Sigdeq as usize],
)
.ok()?;
ret.assume_init()
core::mem::transmute(buf)
};
Some(SiginfoAbi {
si_signo: sig_idx as i32 + 1,
+4 -4
View File
@@ -6,12 +6,12 @@ use core::{
use syscall::{
error::{Error, Result, EINTR},
CallFlags, RtSigInfo, TimeSpec, EINVAL, ERESTART,
CallFlags, TimeSpec, EINVAL, ERESTART,
};
use crate::{
arch::manually_enter_trampoline,
protocol::{ProcCall, ProcKillTarget, ThreadCall, WaitFlags},
protocol::{ProcCall, ProcKillTarget, RtSigInfo, ThreadCall, WaitFlags},
signal::tmp_disable_signals,
DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO,
};
@@ -69,9 +69,9 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> {
uid: 0, // TODO
pid: posix_getpid(),
};
match wrapper(false, false, || {
match wrapper(false, true, || {
this_proc_call(
&mut siginf,
unsafe { plain::as_mut_bytes(&mut siginf) },
CallFlags::empty(),
&[ProcCall::Sigq as usize, pid, sig],
)