Skip to content

Commit

Permalink
fix occasional hang on poweroff
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalmiel committed Sep 27, 2024
1 parent 238d17e commit 067f9d3
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 47 deletions.
12 changes: 10 additions & 2 deletions cykusz-rs/src/arch/x86_64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ pub extern "C" fn fast_syscall_handler(sys_frame: &mut SyscallFrame, regs: &mut
}
} else {
//logln!("syscall {:?} {:?}", regs, sys_frame);
let task = current_task_ref();
dbgln!(
syscall,
"syscall {} {}, ret: 0x{:x}",
"syscall [task {}] {} {}, ret: 0x{:x}",
task.tid(),
regs.rax,
SYSCALL_STRING[regs.rax as usize],
sys_frame.rip
Expand All @@ -62,7 +64,13 @@ pub extern "C" fn fast_syscall_handler(sys_frame: &mut SyscallFrame, regs: &mut
regs.rax, regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9,
);

dbgln!(syscall, "done syscall {} = {:?}", regs.rax, res);
dbgln!(
syscall,
"done syscall [task {}] {} = {:?}",
task.tid(),
SYSCALL_STRING[regs.rax as usize],
res
);

crate::arch::signal::arch_sys_check_signals(res, sys_frame, regs);
}
Expand Down
6 changes: 5 additions & 1 deletion cykusz-rs/src/kernel/sched/round_robin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,17 @@ impl Queues {
if let Some(task) = cursor.remove() {
self.push_runnable_front(task, true);
}
} else {
// if process was not stopped, wake it up in case it has some pending signals to process
self.wake(task, _lock)
}
}

fn exit(&mut self, status: syscall_defs::waitpid::Status, lock: SpinGuard<()>) -> ! {
let current = get_current();

logln!(
dbgln!(
task,
"exit tid: {}, sc: {}, wc: {}, st: {:?}",
current.tid(),
Arc::strong_count(current),
Expand Down
7 changes: 7 additions & 0 deletions cykusz-rs/src/kernel/sched/task_container.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::kernel::sync::{LockApi, Spin};
use crate::kernel::task::Task;
use alloc::sync::Arc;
use syscall_defs::signal::SigProcMask;

pub struct TaskContainer {
tasks: Spin<hashbrown::HashMap<usize, Arc<Task>>>,
Expand Down Expand Up @@ -31,6 +32,12 @@ impl TaskContainer {
pub fn close_all_tasks(&self) {
let init = crate::kernel::init::init_task();

init.signals().set_mask(
SigProcMask::Set,
Some(syscall_defs::signal::SIGCHLD as u64),
None,
);

init.terminate_children();

let tasks = self.tasks.lock();
Expand Down
20 changes: 14 additions & 6 deletions cykusz-rs/src/kernel/task/children_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl WaitPidEvents {

while let Some(t) = cur.get() {
let status = t.waitpid_status();
dbgln!(waitpid, "checking task {} = {:?}", t.tid(), status);
if ((flags.exited() && (status.is_exited() || status.is_signaled()))
|| (flags.continued() && status.is_continued())
|| (flags.stopped() && status.is_stopped()))
Expand Down Expand Up @@ -123,7 +124,7 @@ impl WaitPidEvents {
return Ok(Some(res));
}

return Ok(None);
Ok(None)
}

pub fn wait_thread(
Expand Down Expand Up @@ -152,7 +153,7 @@ impl WaitPidEvents {
status: &mut syscall_defs::waitpid::Status,
flags: WaitPidFlags,
) -> SignalResult<SyscallResult> {
logln4!("{} waitpid {} {:?}", me.tid(), pid, flags);
dbgln!(waitpid, "{} waitpid {} {:?}", me.tid(), pid, flags);
let ret = self.wait_on(me, flags, false, |t| {
if !t.is_process_leader() {
false
Expand All @@ -165,16 +166,23 @@ impl WaitPidEvents {
}
}
});
logln4!("{} waitpid {} {:?} = {:?}", me.tid(), pid, flags, ret);

return match ret {
dbgln!(
waitpid,
"{} waitpid {} {:?} = {:?}",
me.tid(),
pid,
flags,
ret
);

match ret {
Ok(Some((tid, st))) => {
*status = st;

Ok(Ok(tid))
}
Ok(None) => Ok(Err(SyscallError::ECHILD)),
Err(e) => Err(e),
};
}
}
}
94 changes: 60 additions & 34 deletions cykusz-rs/src/kernel/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::arch::mm::VirtAddr;
use crate::arch::task::Task as ArchTask;
use crate::kernel::fs::dirent::DirEntryItem;
use crate::kernel::fs::root_dentry;
use crate::kernel::sched::{new_task_tid, SleepFlags};
use crate::kernel::sched::{current_task_ref, new_task_tid, SleepFlags};
use crate::kernel::signal::{SignalResult, Signals, KSIGSTOPTHR};
use crate::kernel::sync::{LockApi, RwSpin, Spin, SpinGuard};
use crate::kernel::task::children_events::WaitPidEvents;
Expand Down Expand Up @@ -591,39 +591,56 @@ impl Task {
}

pub fn terminate_children(&self) {
for c in self
.children()
.iter()
.filter(|t| t.pid() != self.pid() && t.state() != TaskState::Unused)
{
dbgln!(
poweroff,
"sigkill to {} {}",
c.pid(),
if let Some(e) = c.exe() {
e.full_path()
} else {
String::new()
}
);
c.signal(syscall_defs::signal::SIGKILL);
}
'outer: loop {
for c in self
.children()
.iter()
.filter(|t| t.pid() != self.pid() && t.state() != TaskState::Unused)
{
dbgln!(
poweroff,
"sigkill to {} {}",
c.pid(),
if let Some(e) = c.exe() {
e.full_path()
} else {
String::new()
}
);
c.signal(syscall_defs::signal::SIGKILL);
}

loop {
match self.wait_pid(
-1,
&mut syscall_defs::waitpid::Status::Invalid(0),
syscall_defs::waitpid::WaitPidFlags::all(),
) {
Ok(Err(SyscallError::ECHILD)) => {
break;
}
Ok(Ok(pid)) => {
dbgln!(poweroff, "terminated child pid: {}", pid);
}
Err(_) => continue,
Ok(Err(e)) => {
panic!("Unexpected error from wait_pid {:?}", e);
'inner: loop {
let mut status = syscall_defs::waitpid::Status::Invalid(0);
match self.wait_pid(-1, &mut status, syscall_defs::waitpid::WaitPidFlags::EXITED) {
Ok(Err(SyscallError::ECHILD)) => {
dbgln!(poweroff, "got ECHILD");
break 'outer;
}
Ok(Ok(pid)) => {
dbgln!(
poweroff,
"terminated child pid: {} status: {:?}",
pid,
status
);
}
Err(e) => {
dbgln!(
poweroff,
"got signal error {:?}, pending: {:#x} has_children: {}",
e,
self.signals().pending(),
!self.children.lock().is_empty()
);

if !self.children.lock().is_empty() {
break 'inner;
}
}
Ok(Err(e)) => {
panic!("Unexpected error from wait_pid {:?}", e);
}
}
}
}
Expand Down Expand Up @@ -773,7 +790,13 @@ impl Task {
}

pub fn signal(&self, sig: usize) -> bool {
logln5!("signal {} sig: {}", self.pid(), sig);
dbgln!(
signal,
"{}: signal {} sig: {}",
current_task_ref().tid(),
self.pid(),
sig
);
if self.state() != TaskState::Unused {
self.do_signal(sig, false)
} else {
Expand Down Expand Up @@ -801,6 +824,7 @@ impl Task {
parent.children_events.add_zombie(self.me());

if self.is_process_leader() {
dbgln!(waitpid, "signal zombie SIGCHILD by {}", self.tid());
parent.signal(SIGCHLD);
}
}
Expand All @@ -811,6 +835,7 @@ impl Task {
parent.children_events.add_continued(self.me());

if self.is_process_leader() {
dbgln!(waitpid, "signal cont SIGCHILD by {}", self.tid());
parent.signal(SIGCHLD);
}
}
Expand All @@ -822,6 +847,7 @@ impl Task {
parent.children_events.add_stopped(self.me());

if self.is_process_leader() {
dbgln!(waitpid, "signal stop SIGCHILD by {}", self.tid());
parent.signal(SIGCHLD);
}
}
Expand Down
6 changes: 3 additions & 3 deletions disk-scripts/fsck_disk_fix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set -e
losetup -D
losetup -P /dev/loop0 disk.img

sudo -u $USER fsck.ext2 /dev/loop0p1 -f -v -p
sudo -u $USER fsck.ext2 /dev/loop0p2 -f -v -p
sudo -u $USER fsck.ext2 /dev/loop0p3 -f -v -p
sudo -u $USER fsck.ext2 /dev/loop0p1 -f -v
sudo -u $USER fsck.ext2 /dev/loop0p2 -f -v
sudo -u $USER fsck.ext2 /dev/loop0p3 -f -v

losetup -D
2 changes: 1 addition & 1 deletion disk-scripts/install_os.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fi
sudo umount mnt

PROGS="test testcpp hello stack nyancat ttytest fork poweroff stat fbdoom doom1.wad open_sleep"
RUST_PROGS="init shell mount umount unixsocket-server unixsocket-client forktest mprotecttest, playwav"
RUST_PROGS="init shell mount umount unixsocket-server unixsocket-client forktest mprotecttest playwav"

sudo mount /dev/loop0p2 mnt
sudo chown -R $USER:$USER mnt
Expand Down

0 comments on commit 067f9d3

Please sign in to comment.