Remove deadlock in rc caused by pwait waiting for itself.

The following situation can trigger the deadlock:
1) Long time ago a_service was started through rc.d
2) We want to restart a_service and issue service a_service restart
3) rc.subr reads current process PID (via file or process),
   sends TERM signal and runs pwait with PID harvested
4) a_service process dies very quickly so it's PID becomes available.
   It is possible that while original process was running,
   PID counter overflowed and pwait got assigned a_service's PID.

This patch ignores pid(s) to wait that are equal to pwait PID.

Reported by:	Dan McGregor, Boris Lytochkin
Submitted by:	Boris Lytochkin <lytboris at gmail.com>
Reviewed By:	0mp
MFC after:	2 weeks
PR:		218598
Differential Revision: https://reviews.freebsd.org/D28240
This commit is contained in:
Alexander V. Chernikov 2021-01-21 21:26:15 +00:00
parent 1ac7c34486
commit 5bdce6ff54
2 changed files with 9 additions and 1 deletions

View File

@ -32,7 +32,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd October 5, 2020 .Dd January 21, 2021
.Dt PWAIT 1 .Dt PWAIT 1
.Os .Os
.Sh NAME .Sh NAME
@ -145,6 +145,10 @@ is not a substitute for the
.Xr wait 1 .Xr wait 1
builtin builtin
as it will not clean up any zombies or state in the parent process. as it will not clean up any zombies or state in the parent process.
.Pp
To avoid deadlock,
.Nm
will ignore its own pid, if it is provided as a process id to wait for.
.Sh HISTORY .Sh HISTORY
A A
.Nm .Nm

View File

@ -146,6 +146,10 @@ main(int argc, char *argv[])
warnx("%s: bad process id", s); warnx("%s: bad process id", s);
continue; continue;
} }
if (pid == getpid()) {
warnx("%s: skiping my own pid", s);
continue;
}
for (i = 0; i < nleft; i++) { for (i = 0; i < nleft; i++) {
if (e[i].ident == (uintptr_t)pid) { if (e[i].ident == (uintptr_t)pid) {
break; break;