mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Add sys_signalfd/sys_signalfd implementation
This commit is contained in:
parent
7644ca1598
commit
bce23a63bd
@ -302,14 +302,14 @@ provided by Linux on x86-64 architecture.
|
|||||||
| 279 | move_pages | ❌ |
|
| 279 | move_pages | ❌ |
|
||||||
| 280 | utimensat | ✅ |
|
| 280 | utimensat | ✅ |
|
||||||
| 281 | epoll_pwait | ✅ |
|
| 281 | epoll_pwait | ✅ |
|
||||||
| 282 | signalfd | ❌ |
|
| 282 | signalfd | ✅ |
|
||||||
| 283 | timerfd_create | ❌ |
|
| 283 | timerfd_create | ❌ |
|
||||||
| 284 | eventfd | ✅ |
|
| 284 | eventfd | ✅ |
|
||||||
| 285 | fallocate | ✅ |
|
| 285 | fallocate | ✅ |
|
||||||
| 286 | timerfd_settime | ❌ |
|
| 286 | timerfd_settime | ❌ |
|
||||||
| 287 | timerfd_gettime | ❌ |
|
| 287 | timerfd_gettime | ❌ |
|
||||||
| 288 | accept4 | ✅ |
|
| 288 | accept4 | ✅ |
|
||||||
| 289 | signalfd4 | ❌ |
|
| 289 | signalfd4 | ✅ |
|
||||||
| 290 | eventfd2 | ✅ |
|
| 290 | eventfd2 | ✅ |
|
||||||
| 291 | epoll_create1 | ✅ |
|
| 291 | epoll_create1 | ✅ |
|
||||||
| 292 | dup3 | ✅ |
|
| 292 | dup3 | ✅ |
|
||||||
|
@ -13,6 +13,10 @@ impl SigEvents {
|
|||||||
pub fn new(sig_num: SigNum) -> Self {
|
pub fn new(sig_num: SigNum) -> Self {
|
||||||
Self(sig_num)
|
Self(sig_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sig_num(&self) -> SigNum {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Events for SigEvents {}
|
impl Events for SigEvents {}
|
||||||
|
@ -118,6 +118,14 @@ impl<T: Into<SigSet>> ops::SubAssign<T> for SigSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ops::Not for SigSet {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn not(self) -> Self {
|
||||||
|
SigSet { bits: !self.bits }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SigSet {
|
impl SigSet {
|
||||||
pub fn new_empty() -> Self {
|
pub fn new_empty() -> Self {
|
||||||
SigSet { bits: 0 }
|
SigSet { bits: 0 }
|
||||||
@ -139,9 +147,14 @@ impl SigSet {
|
|||||||
self.bits.count_ones() as usize
|
self.bits.count_ones() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, set: impl Into<Self>) -> bool {
|
pub fn contains(&self, other: impl Into<Self>) -> bool {
|
||||||
let set = set.into();
|
let other = other.into();
|
||||||
self.bits & set.bits == set.bits
|
self.bits & other.bits == other.bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn intersects(&self, other: impl Into<Self>) -> bool {
|
||||||
|
let other = other.into();
|
||||||
|
self.bits & other.bits != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ use crate::syscall::{
|
|||||||
setuid::sys_setuid,
|
setuid::sys_setuid,
|
||||||
shutdown::sys_shutdown,
|
shutdown::sys_shutdown,
|
||||||
sigaltstack::sys_sigaltstack,
|
sigaltstack::sys_sigaltstack,
|
||||||
|
signalfd::sys_signalfd4,
|
||||||
socket::sys_socket,
|
socket::sys_socket,
|
||||||
socketpair::sys_socketpair,
|
socketpair::sys_socketpair,
|
||||||
stat::{sys_fstat, sys_fstatat},
|
stat::{sys_fstat, sys_fstatat},
|
||||||
@ -182,6 +183,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_PWRITEV = 70 => sys_pwritev(args[..4]);
|
SYS_PWRITEV = 70 => sys_pwritev(args[..4]);
|
||||||
SYS_SENDFILE64 = 71 => sys_sendfile(args[..4]);
|
SYS_SENDFILE64 = 71 => sys_sendfile(args[..4]);
|
||||||
SYS_PSELECT6 = 72 => sys_pselect6(args[..6]);
|
SYS_PSELECT6 = 72 => sys_pselect6(args[..6]);
|
||||||
|
SYS_SIGNALFD4 = 74 => sys_signalfd4(args[..4]);
|
||||||
SYS_READLINKAT = 78 => sys_readlinkat(args[..4]);
|
SYS_READLINKAT = 78 => sys_readlinkat(args[..4]);
|
||||||
SYS_NEWFSTATAT = 79 => sys_fstatat(args[..4]);
|
SYS_NEWFSTATAT = 79 => sys_fstatat(args[..4]);
|
||||||
SYS_NEWFSTAT = 80 => sys_fstat(args[..2]);
|
SYS_NEWFSTAT = 80 => sys_fstat(args[..2]);
|
||||||
|
@ -124,6 +124,7 @@ use crate::syscall::{
|
|||||||
setuid::sys_setuid,
|
setuid::sys_setuid,
|
||||||
shutdown::sys_shutdown,
|
shutdown::sys_shutdown,
|
||||||
sigaltstack::sys_sigaltstack,
|
sigaltstack::sys_sigaltstack,
|
||||||
|
signalfd::{sys_signalfd, sys_signalfd4},
|
||||||
socket::sys_socket,
|
socket::sys_socket,
|
||||||
socketpair::sys_socketpair,
|
socketpair::sys_socketpair,
|
||||||
stat::{sys_fstat, sys_fstatat, sys_lstat, sys_stat},
|
stat::{sys_fstat, sys_fstatat, sys_lstat, sys_stat},
|
||||||
@ -320,9 +321,11 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_SET_ROBUST_LIST = 273 => sys_set_robust_list(args[..2]);
|
SYS_SET_ROBUST_LIST = 273 => sys_set_robust_list(args[..2]);
|
||||||
SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]);
|
SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]);
|
||||||
SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]);
|
SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]);
|
||||||
|
SYS_SIGNALFD = 282 => sys_signalfd(args[..3]);
|
||||||
SYS_EVENTFD = 284 => sys_eventfd(args[..1]);
|
SYS_EVENTFD = 284 => sys_eventfd(args[..1]);
|
||||||
SYS_FALLOCATE = 285 => sys_fallocate(args[..4]);
|
SYS_FALLOCATE = 285 => sys_fallocate(args[..4]);
|
||||||
SYS_ACCEPT4 = 288 => sys_accept4(args[..4]);
|
SYS_ACCEPT4 = 288 => sys_accept4(args[..4]);
|
||||||
|
SYS_SIGNALFD4 = 289 => sys_signalfd4(args[..4]);
|
||||||
SYS_EVENTFD2 = 290 => sys_eventfd2(args[..2]);
|
SYS_EVENTFD2 = 290 => sys_eventfd2(args[..2]);
|
||||||
SYS_EPOLL_CREATE1 = 291 => sys_epoll_create1(args[..1]);
|
SYS_EPOLL_CREATE1 = 291 => sys_epoll_create1(args[..1]);
|
||||||
SYS_DUP3 = 292 => sys_dup3(args[..3]);
|
SYS_DUP3 = 292 => sys_dup3(args[..3]);
|
||||||
|
@ -131,6 +131,7 @@ mod setsockopt;
|
|||||||
mod setuid;
|
mod setuid;
|
||||||
mod shutdown;
|
mod shutdown;
|
||||||
mod sigaltstack;
|
mod sigaltstack;
|
||||||
|
mod signalfd;
|
||||||
mod socket;
|
mod socket;
|
||||||
mod socketpair;
|
mod socketpair;
|
||||||
mod stat;
|
mod stat;
|
||||||
|
369
kernel/src/syscall/signalfd.rs
Normal file
369
kernel/src/syscall/signalfd.rs
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//! signalfd implementation for Linux compatibility
|
||||||
|
//!
|
||||||
|
//! The signalfd mechanism allows receiving signals via file descriptor,
|
||||||
|
//! enabling better integration with event loops.
|
||||||
|
//! See https://man7.org/linux/man-pages/man2/signalfd.2.html
|
||||||
|
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use crate::{
|
||||||
|
events::{IoEvents, Observer},
|
||||||
|
fs::{
|
||||||
|
file_handle::FileLike,
|
||||||
|
file_table::{get_file_fast, FdFlags, FileDesc},
|
||||||
|
utils::{CreationFlags, InodeMode, InodeType, Metadata, StatusFlags},
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
process::{
|
||||||
|
posix_thread::AsPosixThread,
|
||||||
|
signal::{
|
||||||
|
constants::{SIGKILL, SIGSTOP},
|
||||||
|
sig_mask::{AtomicSigMask, SigMask},
|
||||||
|
signals::Signal,
|
||||||
|
PollHandle, Pollable, Pollee, SigEvents, SigEventsFilter,
|
||||||
|
},
|
||||||
|
Gid, Uid,
|
||||||
|
},
|
||||||
|
time::clocks::RealTimeClock,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Creates a new signalfd or updates an existing one according to the given mask
|
||||||
|
pub fn sys_signalfd(
|
||||||
|
fd: FileDesc,
|
||||||
|
mask_ptr: Vaddr,
|
||||||
|
sizemask: usize,
|
||||||
|
ctx: &Context,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
|
sys_signalfd4(fd, mask_ptr, sizemask, 0, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new signalfd or updates an existing one according to the given mask and flags
|
||||||
|
pub fn sys_signalfd4(
|
||||||
|
fd: FileDesc,
|
||||||
|
mask_ptr: Vaddr,
|
||||||
|
sizemask: usize,
|
||||||
|
flags: i32,
|
||||||
|
ctx: &Context,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
|
debug!(
|
||||||
|
"fd = {}, mask = {:x}, sizemask = {}, flags = {}",
|
||||||
|
fd, mask_ptr, sizemask, flags
|
||||||
|
);
|
||||||
|
|
||||||
|
if sizemask != core::mem::size_of::<SigMask>() {
|
||||||
|
return Err(Error::with_message(Errno::EINVAL, "invalid mask size"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mask = ctx.user_space().read_val::<SigMask>(mask_ptr)?;
|
||||||
|
mask -= SIGKILL;
|
||||||
|
mask -= SIGSTOP;
|
||||||
|
|
||||||
|
let flags = SignalFileFlags::from_bits(flags as u32)
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?;
|
||||||
|
|
||||||
|
let fd_flags = if flags.contains(SignalFileFlags::O_CLOEXEC) {
|
||||||
|
FdFlags::CLOEXEC
|
||||||
|
} else {
|
||||||
|
FdFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
let non_blocking = flags.contains(SignalFileFlags::O_NONBLOCK);
|
||||||
|
|
||||||
|
let new_fd = if fd == -1 {
|
||||||
|
create_new_signalfd(ctx, mask, non_blocking, fd_flags)?
|
||||||
|
} else {
|
||||||
|
update_existing_signalfd(ctx, fd, mask, non_blocking)?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(SyscallReturn::Return(new_fd as _))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_new_signalfd(
|
||||||
|
ctx: &Context,
|
||||||
|
mask: SigMask,
|
||||||
|
non_blocking: bool,
|
||||||
|
fd_flags: FdFlags,
|
||||||
|
) -> Result<FileDesc> {
|
||||||
|
let atomic_mask = AtomicSigMask::new(mask);
|
||||||
|
let signal_file = SignalFile::new(atomic_mask, non_blocking);
|
||||||
|
|
||||||
|
register_observer(ctx, &signal_file, mask)?;
|
||||||
|
|
||||||
|
let file_table = ctx.thread_local.file_table().borrow();
|
||||||
|
let fd = file_table.write().insert(signal_file, fd_flags);
|
||||||
|
Ok(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_existing_signalfd(
|
||||||
|
ctx: &Context,
|
||||||
|
fd: FileDesc,
|
||||||
|
new_mask: SigMask,
|
||||||
|
non_blocking: bool,
|
||||||
|
) -> Result<FileDesc> {
|
||||||
|
let mut file_table = ctx.thread_local.file_table().borrow_mut();
|
||||||
|
let file = get_file_fast!(&mut file_table, fd);
|
||||||
|
let signal_file = file
|
||||||
|
.downcast_ref::<SignalFile>()
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::EINVAL, "File descriptor is not a signalfd"))?;
|
||||||
|
|
||||||
|
if signal_file.mask().load(Ordering::Relaxed) != new_mask {
|
||||||
|
signal_file.update_signal_mask(new_mask)?;
|
||||||
|
}
|
||||||
|
signal_file.set_non_blocking(non_blocking);
|
||||||
|
Ok(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_observer(ctx: &Context, signal_file: &Arc<SignalFile>, mask: SigMask) -> Result<()> {
|
||||||
|
let filter = SigEventsFilter::new(mask);
|
||||||
|
|
||||||
|
ctx.posix_thread
|
||||||
|
.register_sigqueue_observer(signal_file.observer_ref(), filter);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Signal file descriptor creation flags
|
||||||
|
struct SignalFileFlags: u32 {
|
||||||
|
const O_CLOEXEC = CreationFlags::O_CLOEXEC.bits();
|
||||||
|
const O_NONBLOCK = StatusFlags::O_NONBLOCK.bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Signal file implementation
|
||||||
|
///
|
||||||
|
/// Represents a file that can be used to receive signals
|
||||||
|
/// as readable events.
|
||||||
|
struct SignalFile {
|
||||||
|
/// Atomic signal mask for filtering signals
|
||||||
|
signals_mask: AtomicSigMask,
|
||||||
|
/// I/O event notifier
|
||||||
|
pollee: Pollee,
|
||||||
|
/// Non-blocking mode flag
|
||||||
|
non_blocking: AtomicBool,
|
||||||
|
/// Weak reference to self as an observer
|
||||||
|
weak_self: Weak<dyn Observer<SigEvents>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SignalFile {
|
||||||
|
/// Create a new signalfd instance
|
||||||
|
fn new(mask: AtomicSigMask, non_blocking: bool) -> Arc<Self> {
|
||||||
|
Arc::new_cyclic(|weak_ref| {
|
||||||
|
let weak_self = weak_ref.clone() as Weak<dyn Observer<SigEvents>>;
|
||||||
|
Self {
|
||||||
|
signals_mask: mask,
|
||||||
|
pollee: Pollee::new(),
|
||||||
|
non_blocking: AtomicBool::new(non_blocking),
|
||||||
|
weak_self,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mask(&self) -> &AtomicSigMask {
|
||||||
|
&self.signals_mask
|
||||||
|
}
|
||||||
|
|
||||||
|
fn observer_ref(&self) -> Weak<dyn Observer<SigEvents>> {
|
||||||
|
self.weak_self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_signal_mask(&self, new_mask: SigMask) -> Result<()> {
|
||||||
|
if let Some(thread) = current_thread!().as_posix_thread() {
|
||||||
|
thread.unregister_sigqueue_observer(&self.weak_self);
|
||||||
|
let filter = SigEventsFilter::new(new_mask);
|
||||||
|
thread.register_sigqueue_observer(self.weak_self.clone(), filter);
|
||||||
|
}
|
||||||
|
self.signals_mask.store(new_mask, Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_non_blocking(&self, non_blocking: bool) {
|
||||||
|
self.non_blocking.store(non_blocking, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_non_blocking(&self) -> bool {
|
||||||
|
self.non_blocking.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check current readable I/O events
|
||||||
|
fn check_io_events(&self) -> IoEvents {
|
||||||
|
let current = current_thread!();
|
||||||
|
let Some(thread) = current.as_posix_thread() else {
|
||||||
|
return IoEvents::empty();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mask = self.signals_mask.load(Ordering::Relaxed);
|
||||||
|
if thread.sig_pending().intersects(mask) {
|
||||||
|
IoEvents::IN
|
||||||
|
} else {
|
||||||
|
IoEvents::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempt non-blocking read operation
|
||||||
|
fn try_read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||||
|
let current = current_thread!();
|
||||||
|
let thread = current
|
||||||
|
.as_posix_thread()
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::ESRCH, "Not a POSIX thread"))?;
|
||||||
|
|
||||||
|
// Mask is inverted to get the signals that are not blocked
|
||||||
|
let mask = !self.signals_mask.load(Ordering::Relaxed);
|
||||||
|
let max_signals = writer.avail() / core::mem::size_of::<SignalfdSiginfo>();
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
for _ in 0..max_signals {
|
||||||
|
match thread.dequeue_signal(&mask) {
|
||||||
|
Some(signal) => {
|
||||||
|
writer.write_val(&signal.to_signalfd_siginfo())?;
|
||||||
|
count += 1;
|
||||||
|
self.pollee.invalidate();
|
||||||
|
}
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return_errno!(Errno::EAGAIN);
|
||||||
|
}
|
||||||
|
Ok(count * core::mem::size_of::<SignalfdSiginfo>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Observer<SigEvents> for SignalFile {
|
||||||
|
// TODO: Fix signal notifications.
|
||||||
|
// Child processes do not inherit the parent's observer mechanism for signal event notifications.
|
||||||
|
// `sys_poll` with blocking mode gets stuck if the signal is received after polling.
|
||||||
|
fn on_events(&self, events: &SigEvents) {
|
||||||
|
if self
|
||||||
|
.signals_mask
|
||||||
|
.load(Ordering::Relaxed)
|
||||||
|
.contains(events.sig_num())
|
||||||
|
{
|
||||||
|
self.pollee.notify(IoEvents::IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pollable for SignalFile {
|
||||||
|
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
|
||||||
|
self.pollee
|
||||||
|
.poll_with(mask, poller, || self.check_io_events())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileLike for SignalFile {
|
||||||
|
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||||
|
if writer.avail() < core::mem::size_of::<SignalfdSiginfo>() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "Buffer too small for siginfo structure");
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_non_blocking() {
|
||||||
|
self.try_read(writer)
|
||||||
|
} else {
|
||||||
|
self.wait_events(IoEvents::IN, None, || self.try_read(writer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, _reader: &mut VmReader) -> Result<usize> {
|
||||||
|
return_errno_with_message!(Errno::EBADF, "signalfd does not support write operations");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn status_flags(&self) -> StatusFlags {
|
||||||
|
if self.is_non_blocking() {
|
||||||
|
StatusFlags::O_NONBLOCK
|
||||||
|
} else {
|
||||||
|
StatusFlags::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> {
|
||||||
|
self.set_non_blocking(new_flags.contains(StatusFlags::O_NONBLOCK));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Metadata {
|
||||||
|
let now = RealTimeClock::get().read_time();
|
||||||
|
Metadata {
|
||||||
|
dev: 0,
|
||||||
|
ino: 0,
|
||||||
|
size: 0,
|
||||||
|
blk_size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: now,
|
||||||
|
mtime: now,
|
||||||
|
ctime: now,
|
||||||
|
type_: InodeType::NamedPipe,
|
||||||
|
mode: InodeMode::from_bits_truncate(0o400),
|
||||||
|
nlinks: 1,
|
||||||
|
uid: Uid::new_root(),
|
||||||
|
gid: Gid::new_root(),
|
||||||
|
rdev: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SignalFile {
|
||||||
|
// TODO: Fix signal notifications. See `on_events` method.
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(thread) = current_thread!().as_posix_thread() {
|
||||||
|
thread.unregister_sigqueue_observer(&self.weak_self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone, Pod)]
|
||||||
|
struct SignalfdSiginfo {
|
||||||
|
ssi_signo: u32,
|
||||||
|
ssi_errno: i32,
|
||||||
|
ssi_code: i32,
|
||||||
|
ssi_pid: u32,
|
||||||
|
ssi_uid: u32,
|
||||||
|
ssi_fd: i32,
|
||||||
|
ssi_tid: u32,
|
||||||
|
ssi_band: u32,
|
||||||
|
ssi_overrun: u32,
|
||||||
|
ssi_trapno: u32,
|
||||||
|
ssi_status: i32,
|
||||||
|
ssi_int: i32,
|
||||||
|
ssi_ptr: u64,
|
||||||
|
ssi_utime: u64,
|
||||||
|
ssi_stime: u64,
|
||||||
|
ssi_addr: u64,
|
||||||
|
_pad: [u8; 48],
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ToSignalfdSiginfo {
|
||||||
|
fn to_signalfd_siginfo(&self) -> SignalfdSiginfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToSignalfdSiginfo for Box<dyn Signal> {
|
||||||
|
fn to_signalfd_siginfo(&self) -> SignalfdSiginfo {
|
||||||
|
let siginfo = self.to_info();
|
||||||
|
SignalfdSiginfo {
|
||||||
|
ssi_signo: siginfo.si_signo as _,
|
||||||
|
ssi_errno: siginfo.si_errno,
|
||||||
|
ssi_code: siginfo.si_code,
|
||||||
|
ssi_pid: 0,
|
||||||
|
ssi_uid: 0,
|
||||||
|
ssi_fd: 0,
|
||||||
|
ssi_tid: 0,
|
||||||
|
ssi_band: 0,
|
||||||
|
ssi_overrun: 0,
|
||||||
|
ssi_trapno: 0,
|
||||||
|
ssi_status: 0,
|
||||||
|
ssi_int: 0,
|
||||||
|
ssi_ptr: 0,
|
||||||
|
ssi_utime: 0,
|
||||||
|
ssi_stime: 0,
|
||||||
|
ssi_addr: 0,
|
||||||
|
_pad: [0; 48],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,7 @@ TESTS ?= \
|
|||||||
sendfile_test \
|
sendfile_test \
|
||||||
sigaction_test \
|
sigaction_test \
|
||||||
sigaltstack_test \
|
sigaltstack_test \
|
||||||
|
signalfd_test \
|
||||||
stat_test \
|
stat_test \
|
||||||
stat_times_test \
|
stat_times_test \
|
||||||
statfs_test \
|
statfs_test \
|
||||||
|
6
test/syscall_test/blocklists/signalfd_test
Normal file
6
test/syscall_test/blocklists/signalfd_test
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Signalfd.Ppoll
|
||||||
|
Signalfd/SignalfdTest.Blocking/kSignoMax
|
||||||
|
Signalfd/SignalfdTest.ThreadGroup/kSigno
|
||||||
|
Signalfd/SignalfdTest.ThreadGroup/kSignoMax
|
||||||
|
Signalfd/SignalfdTest.Poll/kSigno
|
||||||
|
Signalfd/SignalfdTest.Poll/kSignoMax
|
Loading…
x
Reference in New Issue
Block a user