Introduce a syscall restart mechanism

This commit is contained in:
Zejun Zhao
2024-12-16 08:34:32 +08:00
committed by Tate, Hongliang Tian
parent b70c4784ed
commit ced0023d6b
9 changed files with 45 additions and 15 deletions

View File

@ -10,6 +10,7 @@ use ostd::sync::Waker;
use super::{
kill::SignalSenderIds,
signal::{
sig_action::SigAction,
sig_mask::{AtomicSigMask, SigMask, SigSet},
sig_num::SigNum,
sig_queues::SigQueues,
@ -220,8 +221,11 @@ impl PosixThread {
/// Enqueues a thread-directed signal. This method should only be used for enqueue kernel
/// signal and fault signal.
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
let signal_number = signal.num();
self.sig_queues.enqueue(signal);
if let Some(waker) = &*self.signalled_waker.lock() {
if self.process().sig_dispositions().lock().get(signal_number) != SigAction::Ign
&& let Some(waker) = &*self.signalled_waker.lock()
{
waker.wake_up();
}
}

View File

@ -28,6 +28,7 @@ pub use sig_stack::{SigStack, SigStackFlags};
use super::posix_thread::PosixThread;
use crate::{
cpu::LinuxAbi,
current_userspace,
prelude::*,
process::{do_exit_group, TermStatus},
@ -41,7 +42,11 @@ pub trait SignalContext {
// TODO: This interface of this method is error prone.
// The method takes an argument for the current thread to optimize its efficiency.
/// Handle pending signal for current process.
pub fn handle_pending_signal(user_ctx: &mut UserContext, ctx: &Context) -> Result<()> {
pub fn handle_pending_signal(
user_ctx: &mut UserContext,
ctx: &Context,
syscall_number: Option<usize>,
) -> Result<()> {
// We first deal with signal in current thread, then signal in current process.
let posix_thread = ctx.posix_thread;
let signal = {
@ -69,6 +74,17 @@ pub fn handle_pending_signal(user_ctx: &mut UserContext, ctx: &Context) -> Resul
restorer_addr,
mask,
} => {
if let Some(syscall_number) = syscall_number
&& user_ctx.syscall_ret() == -(Errno::ERESTARTSYS as i32) as usize
{
if flags.contains(SigActionFlags::SA_RESTART) {
user_ctx.set_syscall_num(syscall_number);
user_ctx.set_instruction_pointer(user_ctx.instruction_pointer() - 2);
} else {
user_ctx.set_syscall_ret(-(Errno::EINTR as i32) as usize);
}
}
if flags.contains(SigActionFlags::SA_RESETHAND) {
// In Linux, SA_RESETHAND corresponds to SA_ONESHOT,
// which means the user handler will be executed only once and then reset to the default.

View File

@ -90,9 +90,6 @@ impl TryFrom<u32> for SigActionFlags {
fn try_from(bits: u32) -> Result<Self> {
let flags = SigActionFlags::from_bits(bits)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid sig action flag"))?;
if flags.contains(SigActionFlags::SA_RESTART) {
warn!("SA_RESTART is not supported");
}
Ok(flags)
}
}