Fix sigsuspend and add it to the sigqueue test.
This commit is contained in:
+27
-7
@@ -673,10 +673,13 @@ pub fn currently_pending_blocked() -> u64 {
|
||||
}
|
||||
pub enum Unreachable {}
|
||||
|
||||
pub fn await_signal_async(set: u64) -> Result<Unreachable> {
|
||||
let mut old = 0;
|
||||
set_sigmask(Some(!set), Some(&mut old))?;
|
||||
// TODO: RAII guard
|
||||
pub fn await_signal_async(inner_allowset: u64) -> Result<Unreachable> {
|
||||
let _guard = tmp_disable_signals();
|
||||
let control = &unsafe { Tcb::current().unwrap() }.os_specific.control;
|
||||
|
||||
let old_allowset = get_allowset_raw(&control.word);
|
||||
set_allowset_raw(&control.word, old_allowset, inner_allowset);
|
||||
|
||||
let res = syscall::nanosleep(
|
||||
&TimeSpec {
|
||||
tv_sec: i64::MAX,
|
||||
@@ -684,12 +687,19 @@ pub fn await_signal_async(set: u64) -> Result<Unreachable> {
|
||||
},
|
||||
&mut TimeSpec::default(),
|
||||
);
|
||||
set_sigmask(Some(old), None)?;
|
||||
set_allowset_raw(&control.word, inner_allowset, old_allowset);
|
||||
|
||||
if res == Err(Error::new(EINTR)) {
|
||||
unsafe {
|
||||
manually_enter_trampoline();
|
||||
}
|
||||
}
|
||||
|
||||
res?;
|
||||
unreachable!()
|
||||
}
|
||||
// TODO: deadline-based API
|
||||
pub fn await_signal_sync(inner_allowset: u64, timeout: &TimeSpec) -> Result<SiginfoAbi> {
|
||||
pub fn await_signal_sync(inner_allowset: u64, timeout: Option<&TimeSpec>) -> Result<SiginfoAbi> {
|
||||
let _guard = tmp_disable_signals();
|
||||
let control = &unsafe { Tcb::current().unwrap() }.os_specific.control;
|
||||
|
||||
@@ -704,7 +714,17 @@ pub fn await_signal_sync(inner_allowset: u64, timeout: &TimeSpec) -> Result<Sigi
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
let res = syscall::nanosleep(&timeout, &mut TimeSpec::default());
|
||||
let res = match timeout {
|
||||
Some(t) => syscall::nanosleep(&t, &mut TimeSpec::default()),
|
||||
None => syscall::nanosleep(
|
||||
&TimeSpec {
|
||||
tv_sec: i64::MAX,
|
||||
tv_nsec: 0,
|
||||
},
|
||||
&mut TimeSpec::default(),
|
||||
),
|
||||
};
|
||||
|
||||
let thread_pending = set_allowset_raw(&control.word, inner_allowset, old_allowset);
|
||||
let proc_pending = PROC_CONTROL_STRUCT.pending.load(Ordering::Acquire);
|
||||
|
||||
|
||||
@@ -380,13 +380,20 @@ pub unsafe extern "C" fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigtimedwait(
|
||||
set: *const sigset_t,
|
||||
sig: *mut siginfo, // https://github.com/mozilla/cbindgen/issues/621
|
||||
// s/siginfo_t/siginfo due to https://github.com/mozilla/cbindgen/issues/621
|
||||
sig: *mut siginfo,
|
||||
// POSIX leaves behavior unspecified if this is NULL, but on both Linux and Redox, NULL is used
|
||||
// to differentiate between sigtimedwait and sigwaitinfo internally
|
||||
tp: *const timespec,
|
||||
) -> c_int {
|
||||
Sys::sigtimedwait(&*set, sig.as_mut(), &*tp)
|
||||
Sys::sigtimedwait(&*set, sig.as_mut(), tp.as_ref())
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigwaitinfo(set: *const sigset_t, sig: *mut siginfo_t) -> c_int {
|
||||
sigtimedwait(set, sig, core::ptr::null())
|
||||
}
|
||||
|
||||
pub const _signal_strings: [&str; 32] = [
|
||||
"Unknown signal\0",
|
||||
|
||||
@@ -165,14 +165,14 @@ impl PalSignal for Sys {
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
sig: Option<&mut siginfo_t>,
|
||||
tp: ×pec,
|
||||
tp: Option<×pec>,
|
||||
) -> Result<(), Errno> {
|
||||
unsafe {
|
||||
e_raw(syscall!(
|
||||
RT_SIGTIMEDWAIT,
|
||||
set as *const _,
|
||||
sig.map_or_else(core::ptr::null_mut, |s| s as *mut _) as usize,
|
||||
tp as *const _,
|
||||
sig.map_or_else(core::ptr::null_mut, |s| s as *mut _),
|
||||
tp.map_or_else(core::ptr::null, |t| t as *const _),
|
||||
NSIG / 8
|
||||
))
|
||||
.map(|_| ())
|
||||
|
||||
@@ -42,6 +42,6 @@ pub trait PalSignal: Pal {
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
sig: Option<&mut siginfo_t>,
|
||||
tp: ×pec,
|
||||
tp: Option<×pec>,
|
||||
) -> Result<(), Errno>;
|
||||
}
|
||||
|
||||
@@ -274,14 +274,14 @@ impl PalSignal for Sys {
|
||||
fn sigtimedwait(
|
||||
set: &sigset_t,
|
||||
info_out: Option<&mut siginfo_t>,
|
||||
timeout: ×pec,
|
||||
timeout: Option<×pec>,
|
||||
) -> Result<(), Errno> {
|
||||
// TODO: deadline-based API
|
||||
let timeout = syscall::TimeSpec {
|
||||
let timeout = timeout.map(|timeout| syscall::TimeSpec {
|
||||
tv_sec: timeout.tv_sec,
|
||||
tv_nsec: timeout.tv_nsec as _,
|
||||
};
|
||||
let info = redox_rt::signal::await_signal_sync(*set, &timeout)?.into();
|
||||
});
|
||||
let info = redox_rt::signal::await_signal_sync(*set, timeout.as_ref())?.into();
|
||||
if let Some(out) = info_out {
|
||||
*out = info;
|
||||
}
|
||||
|
||||
+25
-7
@@ -24,11 +24,11 @@ void validate(int sig, const siginfo_t *info) {
|
||||
}
|
||||
|
||||
void action(int sig, siginfo_t *info, void *context) {
|
||||
num++;
|
||||
(void)context;
|
||||
assert(context != NULL);
|
||||
validate(sig, info);
|
||||
write(1, "action\n", 7);
|
||||
num++;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
@@ -40,12 +40,6 @@ int main(void) {
|
||||
parent = getpid();
|
||||
assert(parent != 0);
|
||||
|
||||
int child = fork();
|
||||
ERROR_IF(fork, child, == -1);
|
||||
|
||||
status = close(fds[child == 0 ? 0 : 1]);
|
||||
ERROR_IF(close, status, == -1);
|
||||
|
||||
sigset_t set, mask;
|
||||
status = sigfillset(&mask);
|
||||
ERROR_IF(sigfillset, status, == -1);
|
||||
@@ -67,6 +61,16 @@ int main(void) {
|
||||
status = sigaddset(&set, THE_SIG);
|
||||
ERROR_IF(sigaddset, status, == -1);
|
||||
|
||||
sigset_t empty_set;
|
||||
status = sigemptyset(&empty_set);
|
||||
ERROR_IF(sigemptyset, status, == -1);
|
||||
|
||||
int child = fork();
|
||||
ERROR_IF(fork, child, == -1);
|
||||
|
||||
status = close(fds[child == 0 ? 0 : 1]);
|
||||
ERROR_IF(close, status, == -1);
|
||||
|
||||
struct sigaction sa;
|
||||
memcpy(&sa.sa_mask, &set, sizeof (sigset_t));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
@@ -84,6 +88,20 @@ int main(void) {
|
||||
validate(THE_SIG, &info);
|
||||
assert(num == 0); // ensure no signal handler ran
|
||||
|
||||
num++;
|
||||
|
||||
// TODO: check status
|
||||
status = sigsuspend(&empty_set);
|
||||
if (status == -1) {
|
||||
perror("error in sigsuspend");
|
||||
puts("[EINTR] is usually expected");
|
||||
}
|
||||
|
||||
assert(num == 2); // ensure signal handler ran
|
||||
|
||||
status = sigprocmask(SIG_SETMASK, &empty_set, NULL);
|
||||
ERROR_IF(sigprocmask, status, == -1);
|
||||
|
||||
while (num < 31) {}
|
||||
|
||||
status = write(fds[1], "A", 1);
|
||||
|
||||
Reference in New Issue
Block a user