kernel: fix waitpid() with WSTOPPED; only return on state change?

This commit is contained in:
K. Lange 2022-08-18 18:19:15 +09:00
parent d600d3d393
commit dd33c722c5
2 changed files with 9 additions and 4 deletions

View File

@ -996,9 +996,12 @@ int waitpid(int pid, int * status, int options) {
candidate = child; candidate = child;
break; break;
} }
if ((options & WSTOPPED) && child->flags & PROC_FLAG_SUSPENDED) { if (child->flags & PROC_FLAG_SUSPENDED) {
candidate = child; int status = child->status;
break; if (((options & WSTOPPED) && (status & 0x7F) == 0x7F) || ((options & WUNTRACED) && status == 0x7F)) {
candidate = child;
break;
}
} }
} }
} }
@ -1027,6 +1030,7 @@ int waitpid(int pid, int * status, int options) {
if (status) { if (status) {
*status = candidate->status; *status = candidate->status;
} }
candidate->status = 0;
int pid = candidate->id; int pid = candidate->id;
if (is_parent && (candidate->flags & PROC_FLAG_FINISHED)) { if (is_parent && (candidate->flags & PROC_FLAG_FINISHED)) {
while (*((volatile int *)&candidate->flags) & PROC_FLAG_RUNNING); while (*((volatile int *)&candidate->flags) & PROC_FLAG_RUNNING);

View File

@ -294,6 +294,7 @@ int group_send_signal(pid_t group, int signal, int force_root) {
* @param r Userspace registers before signal entry. * @param r Userspace registers before signal entry.
*/ */
void process_check_signals(struct regs * r) { void process_check_signals(struct regs * r) {
_tryagain:
spin_lock(sig_lock); spin_lock(sig_lock);
if (this_core->current_process && !(this_core->current_process->flags & PROC_FLAG_FINISHED)) { if (this_core->current_process && !(this_core->current_process->flags & PROC_FLAG_FINISHED)) {
/* Set an pending signals that were previously blocked */ /* Set an pending signals that were previously blocked */
@ -305,7 +306,7 @@ void process_check_signals(struct regs * r) {
this_core->current_process->pending_signals &= ~(1 << signal); this_core->current_process->pending_signals &= ~(1 << signal);
spin_unlock(sig_lock); spin_unlock(sig_lock);
if (handle_signal((process_t*)this_core->current_process, signal, r)) return; if (handle_signal((process_t*)this_core->current_process, signal, r)) return;
spin_lock(sig_lock); goto _tryagain;
} }
active_signals >>= 1; active_signals >>= 1;
signal++; signal++;