1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 21:27:44 +00:00

Fix bug where a signal-interrupted waitpid() wouldn't return EINTR.

This commit is contained in:
Andreas Kling 2018-11-28 23:30:06 +01:00
parent 464a16afa2
commit f5a83c4d8a
3 changed files with 15 additions and 9 deletions

View file

@ -1464,7 +1464,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
}
}
m_waitee = waitee;
m_waitee_pid = waitee;
block(BlockedWait);
sched_yield();
if (m_was_interrupted_while_blocked)
@ -1472,17 +1472,20 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
Process* waitee_process;
{
InterruptDisabler disabler;
// NOTE: If waitee was -1, m_waitee will have been filled in by the scheduler.
waitee_process = Process::from_pid(m_waitee);
waitee_process = Process::from_pid(m_waitee_pid);
}
ASSERT(waitee_process);
exit_status = reap(*waitee_process);
return m_waitee;
return m_waitee_pid;
}
void Process::unblock()
{
if (current == this) {
kprintf("ignoring unblock() on current, %s(%u) {%s}\n", name().characters(), pid(), toString(state()));
return;
}
ASSERT(m_state != Process::Runnable && m_state != Process::Running);
system.nblocked--;
m_state = Process::Runnable;

View file

@ -187,7 +187,7 @@ public:
void did_schedule() { ++m_timesScheduled; }
dword timesScheduled() const { return m_timesScheduled; }
pid_t waitee() const { return m_waitee; }
pid_t waitee_pid() const { return m_waitee_pid; }
dword framePtr() const { return m_tss.ebp; }
dword stackPtr() const { return m_tss.esp; }
@ -265,7 +265,7 @@ private:
int m_error { 0 };
void* m_kernelStack { nullptr };
dword m_timesScheduled { 0 };
pid_t m_waitee { -1 };
pid_t m_waitee_pid { -1 };
int m_fdBlockedOnRead { -1 };
int m_blocked_fd { -1 };
size_t m_max_open_file_descriptors { 16 };

View file

@ -38,8 +38,8 @@ bool Scheduler::pick_next()
process.for_each_child([&process] (Process& child) {
if (child.state() != Process::Dead)
return true;
if (process.waitee() == -1 || process.waitee() == child.pid()) {
process.m_waitee = child.pid();
if (process.waitee_pid() == -1 || process.waitee_pid() == child.pid()) {
process.m_waitee_pid = child.pid();
process.unblock();
return false;
}
@ -99,9 +99,12 @@ bool Scheduler::pick_next()
// syscall effectively being "interrupted" despite having completed?
if (process.in_kernel() && !process.is_blocked())
return true;
// NOTE: dispatch_one_pending_signal() may unblock the process.
bool was_blocked = process.is_blocked();
if (!process.dispatch_one_pending_signal())
return true;
if (process.is_blocked()) {
if (was_blocked) {
dbgprintf("Unblock %s(%u) due to signal\n", process.name().characters(), process.pid());
process.m_was_interrupted_while_blocked = true;
process.unblock();
}