Make stop_all_proc_block interruptible to avoid deadlock with parallel suspension

If we try to single-thread a process which thread entered
procctl(REAP_KILL_SUBTREE), and sleeping waiting for us unlocking
stop_all_proc_blocker, we must be able to finish single-threading.  This
requires the sleep to be interruptible.

Reported and tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D35310
This commit is contained in:
Konstantin Belousov 2022-05-01 02:29:25 +03:00
parent 2d5ef216b6
commit 008b2e6544
3 changed files with 7 additions and 6 deletions

View File

@ -3399,10 +3399,10 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_VM_LAYOUT, vm_layout, CTLFLAG_RD |
static struct sx stop_all_proc_blocker;
SX_SYSINIT(stop_all_proc_blocker, &stop_all_proc_blocker, "sapblk");
void
bool
stop_all_proc_block(void)
{
sx_xlock(&stop_all_proc_blocker);
return (sx_xlock_sig(&stop_all_proc_blocker) == 0);
}
void
@ -3426,7 +3426,8 @@ stop_all_proc(void)
int r, gen;
bool restart, seen_stopped, seen_exiting, stopped_some;
stop_all_proc_block();
if (!stop_all_proc_block())
return;
cp = curproc;
allproc_loop:

View File

@ -1063,8 +1063,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
sapblk = false;
if (cmd_info->sapblk != NULL) {
sapblk = cmd_info->sapblk(td, data);
if (sapblk)
stop_all_proc_block();
if (sapblk && !stop_all_proc_block())
return (ERESTART);
}
switch (cmd_info->lock_tree) {

View File

@ -1238,7 +1238,7 @@ void thread_unlink(struct thread *td);
void thread_unsuspend(struct proc *p);
void thread_wait(struct proc *p);
void stop_all_proc_block(void);
bool stop_all_proc_block(void);
void stop_all_proc_unblock(void);
void stop_all_proc(void);
void resume_all_proc(void);