Skip to content

Commit

Permalink
fix: pipe 读取/写入阻塞时,无法kill进程的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin committed Aug 13, 2024
1 parent a1fc824 commit 3310e50
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 79 deletions.
7 changes: 4 additions & 3 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ bitmap = { path = "crates/bitmap" }
driver_base_macros = { "path" = "crates/driver_base_macros" }
# 一个no_std的hashmap、hashset
elf = { version = "=0.7.2", default-features = false }
fdt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt", rev = "9862813020" }
hashbrown = "=0.13.2"
ida = { path = "src/libs/ida" }
intertrait = { path = "crates/intertrait" }
Expand All @@ -48,11 +49,11 @@ num-derive = "=0.3"
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
smoltcp = { version = "=0.11.0", default-features = false, features = ["log", "alloc", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]}
system_error = { path = "crates/system_error" }
unified-init = { path = "crates/unified-init" }
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "f91c807965" }
fdt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt", rev = "9862813020" }
uefi = { version = "=0.26.0", features = ["alloc"] }
uefi-raw = "=0.5.0"
unified-init = { path = "crates/unified-init" }
virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "f91c807965" }
wait_queue_macros = { path = "crates/wait_queue_macros" }
paste = "=1.0.14"
slabmalloc = { path = "crates/rust-slabmalloc" }
log = "0.4.21"
Expand Down
7 changes: 7 additions & 0 deletions kernel/crates/wait_queue_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "wait_queue_macros"
version = "0.1.0"
edition = "2021"
authors = ["longjin <[email protected]>"]

[dependencies]
60 changes: 60 additions & 0 deletions kernel/crates/wait_queue_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#![no_std]

/// Wait for a condition to become true.
///
/// This macro will wait for a condition to become true.
///
/// ## Parameters
///
/// - `$wq`: The wait queue to wait on.
/// - `$condition`: The condition to wait for. (you can pass a function or a boolean expression)
/// - `$cmd`: The command to execute while waiting.
#[macro_export]
macro_rules! wq_wait_event_interruptible {
($wq:expr, $condition: expr, $cmd: expr) => {{
let mut retval = Ok(());
if !$condition {
retval = wait_queue_macros::_wq_wait_event_interruptible!($wq, $condition, $cmd);
}

retval
}};
}

#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! _wq_wait_event_interruptible {
($wq:expr, $condition: expr, $cmd: expr) => {{
wait_queue_macros::__wq_wait_event!($wq, $condition, true, Ok(()), {
$cmd;
crate::sched::schedule(SchedMode::SM_NONE)
})
}};
}

#[macro_export]
macro_rules! __wq_wait_event(
($wq:expr, $condition: expr, $interruptible: expr, $ret: expr, $cmd:expr) => {{
let mut retval = $ret;
let mut exec_finish_wait = true;
loop {
let x = $wq.prepare_to_wait_event($interruptible);
if $condition {
break;
}

if $interruptible && !x.is_ok() {
retval = x;
exec_finish_wait = false;
break;
}

$cmd;
}
if exec_finish_wait {
$wq.finish_wait();
}

retval
}};
);
6 changes: 6 additions & 0 deletions kernel/src/arch/x86_64/interrupt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ pub struct TrapFrame {
pub ss: ::core::ffi::c_ulong,
}

impl Default for TrapFrame {
fn default() -> Self {
Self::new()
}
}

impl TrapFrame {
pub fn new() -> Self {
Self {
Expand Down
32 changes: 28 additions & 4 deletions kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,14 @@ impl File {

let len = self
.inode
.read_at(offset, len, buf, self.private_data.lock())?;
.read_at(offset, len, buf, self.private_data.lock())
.map_err(|e| {
if e == SystemError::ERESTARTSYS {
SystemError::EINTR
} else {
e
}
})?;

if update_offset {
self.offset
Expand All @@ -261,11 +268,24 @@ impl File {

// 如果文件指针已经超过了文件大小,则需要扩展文件大小
if offset > self.inode.metadata()?.size as usize {
self.inode.resize(offset)?;
self.inode.resize(offset).map_err(|e| {
if e == SystemError::ERESTARTSYS {
SystemError::EINTR
} else {
e
}
})?;
}
let len = self
.inode
.write_at(offset, len, buf, self.private_data.lock())?;
.write_at(offset, len, buf, self.private_data.lock())
.map_err(|e| {
if e == SystemError::ERESTARTSYS {
SystemError::EINTR
} else {
e
}
})?;

if update_offset {
self.offset
Expand Down Expand Up @@ -545,7 +565,11 @@ pub struct FileDescriptorVec {
/// 当前进程打开的文件描述符
fds: Vec<Option<Arc<File>>>,
}

impl Default for FileDescriptorVec {
fn default() -> Self {
Self::new()
}
}
impl FileDescriptorVec {
pub const PROCESS_MAX_FD: usize = 1024;

Expand Down
50 changes: 33 additions & 17 deletions kernel/src/ipc/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{
arch::CurrentIrqArch,
exception::InterruptArch,
filesystem::vfs::{
core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem,
FileType, IndexNode, Metadata,
Expand All @@ -10,8 +8,8 @@ use crate::{
wait_queue::WaitQueue,
},
net::event_poll::{EPollEventType, EPollItem, EventPoll},
process::ProcessState,
sched::{schedule, SchedMode},
process::{ProcessManager, ProcessState},
sched::SchedMode,
time::PosixTimeSpec,
};

Expand Down Expand Up @@ -104,6 +102,10 @@ impl InnerPipeInode {
self.epitems.lock().push_back(epitem);
Ok(())
}

fn buf_full(&self) -> bool {
return self.valid_cnt as usize == PIPE_BUFF_SIZE;
}
}

impl LockedPipeInode {
Expand Down Expand Up @@ -150,6 +152,16 @@ impl LockedPipeInode {
pub fn inner(&self) -> &SpinLock<InnerPipeInode> {
&self.inner
}

fn readable(&self) -> bool {
let inode = self.inner.lock();
return inode.valid_cnt > 0 || inode.writer == 0;
}

fn writeable(&self) -> bool {
let inode = self.inner.lock();
return !inode.buf_full() || inode.reader == 0;
}
}

impl IndexNode for LockedPipeInode {
Expand All @@ -173,6 +185,7 @@ impl IndexNode for LockedPipeInode {
if buf.len() < len {
return Err(SystemError::EINVAL);
}
// log::debug!("pipe mode: {:?}", mode);
// 加锁
let mut inode = self.inner.lock();

Expand All @@ -193,14 +206,12 @@ impl IndexNode for LockedPipeInode {
}

// 否则在读等待队列中睡眠,并释放锁
unsafe {
let irq_guard = CurrentIrqArch::save_and_disable_irq();

drop(inode);
self.read_wait_queue.sleep_without_schedule();
drop(irq_guard);
drop(inode);
let r = wq_wait_event_interruptible!(self.read_wait_queue, self.readable(), {});
if r.is_err() {
return Err(SystemError::ERESTARTSYS);
}
schedule(SchedMode::SM_NONE);

inode = self.inner.lock();
}

Expand Down Expand Up @@ -263,6 +274,13 @@ impl IndexNode for LockedPipeInode {
guard.writer += 1;
}

log::debug!(
"pid: {:?} open pipe, reader: {:?}, writer: {:?}, mode: {mode:?}",
ProcessManager::current_pid(),
guard.reader,
guard.writer
);

// 设置mode
*data = FilePrivateData::Pipefs(PipeFsPrivateData { mode: *mode });

Expand Down Expand Up @@ -351,13 +369,11 @@ impl IndexNode for LockedPipeInode {
}

// 解锁并睡眠
unsafe {
let irq_guard = CurrentIrqArch::save_and_disable_irq();
drop(inode);
self.write_wait_queue.sleep_without_schedule();
drop(irq_guard);
drop(inode);
let r = wq_wait_event_interruptible!(self.write_wait_queue, self.writeable(), {});
if r.is_err() {
return Err(SystemError::ERESTARTSYS);
}
schedule(SchedMode::SM_NONE);
inode = self.inner.lock();
}

Expand Down
29 changes: 29 additions & 0 deletions kernel/src/ipc/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@ use super::signal_types::{
};

impl Signal {
pub fn signal_pending_state(
interruptible: bool,
task_wake_kill: bool,
pcb: &Arc<ProcessControlBlock>,
) -> bool {
if !interruptible && !task_wake_kill {
return false;
}

if !pcb.has_pending_signal() {
return false;
}

return interruptible || Self::fatal_signal_pending(pcb);
}

/// 判断当前进程是否收到了SIGKILL信号
pub fn fatal_signal_pending(pcb: &Arc<ProcessControlBlock>) -> bool {
let guard = pcb.sig_info_irqsave();
if guard
.sig_pending()
.signal()
.contains(Signal::SIGKILL.into())
{
return true;
}

return false;
}
/// 向目标进程发送信号
///
/// ## 参数
Expand Down
6 changes: 6 additions & 0 deletions kernel/src/ipc/signal_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ impl SignalStruct {
}
}

impl Default for SignalStruct {
fn default() -> Self {
Self::new()
}
}

impl Deref for SignalStruct {
type Target = InnerSignalStruct;

Expand Down
3 changes: 3 additions & 0 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![feature(c_void_variant)]
#![feature(extract_if)]
#![feature(fn_align)]
#![feature(linked_list_retain)]
#![feature(naked_functions)]
#![feature(new_uninit)]
#![feature(ptr_internals)]
Expand Down Expand Up @@ -83,6 +84,8 @@ extern crate x86;
extern crate klog_types;
extern crate uefi;
extern crate uefi_raw;
#[macro_use]
extern crate wait_queue_macros;

use crate::mm::allocator::kernel_allocator::KernelAllocator;

Expand Down
31 changes: 30 additions & 1 deletion kernel/src/libs/wait_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::intrinsics::unlikely;

use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
use log::{error, warn};
use system_error::SystemError;

use crate::{
arch::CurrentIrqArch,
Expand Down Expand Up @@ -32,6 +33,34 @@ impl WaitQueue {
WaitQueue(SpinLock::new(InnerWaitQueue::INIT))
}

pub fn prepare_to_wait_event(&self, interruptible: bool) -> Result<(), SystemError> {
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
let pcb = ProcessManager::current_pcb();
if pcb.has_pending_signal() {
return Err(SystemError::ERESTARTSYS);
} else {
ProcessManager::mark_sleep(interruptible).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
});
guard.wait_list.push_back(ProcessManager::current_pcb());
drop(guard);
}
Ok(())
}

pub fn finish_wait(&self) {
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info().inner_lock_write_irqsave();
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();

writer.set_state(ProcessState::Runnable);
writer.set_wakeup();

guard.wait_list.retain(|x| !Arc::ptr_eq(x, &pcb));
drop(guard);
drop(writer);
}

/// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
pub fn sleep(&self) {
before_sleep_check(0);
Expand All @@ -50,7 +79,7 @@ impl WaitQueue {
F: FnOnce(),
{
before_sleep_check(0);
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
panic!("sleep error: {:?}", e);
Expand Down
6 changes: 6 additions & 0 deletions kernel/src/mm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,12 @@ pub struct PageFlags<Arch> {
phantom: PhantomData<Arch>,
}

impl<Arch: MemoryManagementArch> Default for PageFlags<Arch> {
fn default() -> Self {
Self::new()
}
}

#[allow(dead_code)]
impl<Arch: MemoryManagementArch> PageFlags<Arch> {
#[inline(always)]
Expand Down
Loading

0 comments on commit 3310e50

Please sign in to comment.