Make SIGSTOP working for sleeps done while waiting for fifo readers or

writers in open(2), when the fifo is located on an NFS mount.

Reported by:	bde
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2015-01-18 15:03:26 +00:00
parent 9cac79b378
commit e3612a4c1f
3 changed files with 13 additions and 4 deletions

View File

@ -137,7 +137,7 @@ fifo_open(ap)
struct thread *td; struct thread *td;
struct fifoinfo *fip; struct fifoinfo *fip;
struct pipe *fpipe; struct pipe *fpipe;
int error; int error, stops_deferred;
vp = ap->a_vp; vp = ap->a_vp;
fp = ap->a_fp; fp = ap->a_fp;
@ -188,8 +188,11 @@ fifo_open(ap)
if ((ap->a_mode & O_NONBLOCK) == 0) { if ((ap->a_mode & O_NONBLOCK) == 0) {
if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
VOP_UNLOCK(vp, 0); VOP_UNLOCK(vp, 0);
stops_deferred = sigallowstop();
error = msleep(&fip->fi_readers, PIPE_MTX(fpipe), error = msleep(&fip->fi_readers, PIPE_MTX(fpipe),
PDROP | PCATCH | PSOCK, "fifoor", 0); PDROP | PCATCH | PSOCK, "fifoor", 0);
if (stops_deferred)
sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (error) { if (error) {
fip->fi_readers--; fip->fi_readers--;
@ -212,8 +215,11 @@ fifo_open(ap)
} }
if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
VOP_UNLOCK(vp, 0); VOP_UNLOCK(vp, 0);
stops_deferred = sigallowstop();
error = msleep(&fip->fi_writers, PIPE_MTX(fpipe), error = msleep(&fip->fi_writers, PIPE_MTX(fpipe),
PDROP | PCATCH | PSOCK, "fifoow", 0); PDROP | PCATCH | PSOCK, "fifoow", 0);
if (stops_deferred)
sigdeferstop();
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (error) { if (error) {
fip->fi_writers--; fip->fi_writers--;

View File

@ -2587,15 +2587,18 @@ sigdeferstop(void)
* not immediately suspend if a stop was posted. Instead, the thread * not immediately suspend if a stop was posted. Instead, the thread
* will suspend either via ast() or a subsequent interruptible sleep. * will suspend either via ast() or a subsequent interruptible sleep.
*/ */
void int
sigallowstop() sigallowstop(void)
{ {
struct thread *td; struct thread *td;
int prev;
td = curthread; td = curthread;
thread_lock(td); thread_lock(td);
prev = (td->td_flags & TDF_SBDRY) != 0;
td->td_flags &= ~TDF_SBDRY; td->td_flags &= ~TDF_SBDRY;
thread_unlock(td); thread_unlock(td);
return (prev);
} }
/* /*

View File

@ -325,7 +325,7 @@ extern struct mtx sigio_lock;
int cursig(struct thread *td); int cursig(struct thread *td);
int sigdeferstop(void); int sigdeferstop(void);
void sigallowstop(void); int sigallowstop(void);
void execsigs(struct proc *p); void execsigs(struct proc *p);
void gsignal(int pgid, int sig, ksiginfo_t *ksi); void gsignal(int pgid, int sig, ksiginfo_t *ksi);
void killproc(struct proc *p, char *why); void killproc(struct proc *p, char *why);