Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Jun 2018 21:03:02 +0000
From:      Rick Macklem <rmacklem@uoguelph.ca>
To:        "freebsd-current@freebsd.org" <freebsd-current@freebsd.org>
Cc:        "kib@FreeBSD.org" <kib@FreeBSD.org>, Alexander Motin <mav@FreeBSD.org>
Subject:   nfsd kernel threads won't die via SIGKILL
Message-ID:  <YTXPR0101MB0959B4E960B85ACAC07B819DDD740@YTXPR0101MB0959.CANPRD01.PROD.OUTLOOK.COM>

next in thread | raw e-mail | index | archive | help
During testing of the pNFS server I have been frequently killing/restarting=
 the nfsd.
Once in a while, the "slave" nfsd process doesn't terminate and a "ps axHl"=
 shows:
  0 48889     1   0   20  0  5884  812 svcexit  D     -   0:00.01 nfsd: ser=
ver=20
  0 48889     1   0   40  0  5884  812 rpcsvc   I     -   0:00.00 nfsd: ser=
ver=20
... more of the same
  0 48889     1   0   40  0  5884  812 rpcsvc   I     -   0:00.00 nfsd: ser=
ver=20
  0 48889     1   0   -8  0  5884  812 rpcsvc   I     -   1:51.78 nfsd: ser=
ver=20
  0 48889     1   0   -8  0  5884  812 rpcsvc   I     -   2:27.75 nfsd: ser=
ver=20

You can see that the top thread (the one that was created with the process)=
 is
stuck in "D"  on "svcexit".
The rest of the threads are still servicing NFS RPCs. If you still have an =
NFS mount on
the server, the mount continues to work and the CPU time for the last two t=
hreads
slowly climbs, due to NFS RPC activity. A SIGKILL was posted for the proces=
s and
these threads (created by kthread_add) are here, but the
cv_wait_sig/cv_timedwait_sig never seems to return EINTR for these other th=
reads.

                       if (ismaster || (!ismaster &&
1207 	                            grp->sg_threadcount > grp->sg_minthreads)=
)
1208 	                                error =3D cv_timedwait_sig(&st->st_co=
nd,
1209 	                                    &grp->sg_lock, 5 * hz);
1210 	                        else
1211 	                                error =3D cv_wait_sig(&st->st_cond,
1212 	                                    &grp->sg_lock);

The top thread (referred to in svc.c as "ismaster" did return from here wit=
h EINTR
and has now done an msleep() here, waiting for the other threads to termina=
te.

       /* Waiting for threads to stop. */
1387 	        for (g =3D 0; g < pool->sp_groupcount; g++) {
1388 	                grp =3D &pool->sp_groups[g];
1389 	                mtx_lock(&grp->sg_lock);
1390 	                while (grp->sg_threadcount > 0)
1391 	                        msleep(grp, &grp->sg_lock, 0, "svcexit", 0);
1392 	                mtx_unlock(&grp->sg_lock);
1393 	        }

Although I can't be sure if this patch has fixed the problem because it hap=
pens
intermittently, I have not seen the problem since applying this patch:
--- rpc/svc.c.sav	2018-06-21 22:52:11.623955000 -0400
+++ rpc/svc.c	2018-06-22 09:01:40.271803000 -0400
@@ -1388,7 +1388,7 @@ svc_run(SVCPOOL *pool)
 		grp =3D &pool->sp_groups[g];
 		mtx_lock(&grp->sg_lock);
 		while (grp->sg_threadcount > 0)
-			msleep(grp, &grp->sg_lock, 0, "svcexit", 0);
+			msleep(grp, &grp->sg_lock, 0, "svcexit", 1);
 		mtx_unlock(&grp->sg_lock);
 	}
 }

As you can see, all it does is add a timeout to the msleep().=20
I am not familiar with the signal delivery code in sleepqeue, so it probabl=
y
isn't correct, but my theory is alonge the lines of...

Since the msleep() doesn't have PCATCH, it does not set TDF_SINTR
and if that happens before the other threads return EINTR from cv_wait_sig(=
),
they no longer do so?
And I thought that waking up from the msleep() via timeouts would maybe all=
ow
the other threads to return EINTR from cv_wait_sig()?

Does this make sense? rick
ps: I'll post if I see the problem again with the patch applied.
pss: This is a single core i386 system, just in case that might affect this=
.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YTXPR0101MB0959B4E960B85ACAC07B819DDD740>