diff options
author | kib <kib@FreeBSD.org> | 2015-01-25 13:09:53 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-01-25 13:09:53 +0000 |
commit | 9ddc339f8bfb9d591096aa6d52debc019b7dbd06 (patch) | |
tree | 3bcdb13b4c31b879ba2265e39b65de7c88e20829 | |
parent | 65e2f9460344e1eebe2ed160db1b56b96ab407fa (diff) | |
download | FreeBSD-src-9ddc339f8bfb9d591096aa6d52debc019b7dbd06.zip FreeBSD-src-9ddc339f8bfb9d591096aa6d52debc019b7dbd06.tar.gz |
MFC r277321:
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.
-rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 8 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 7 | ||||
-rw-r--r-- | sys/sys/signalvar.h | 2 |
3 files changed, 13 insertions, 4 deletions
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index a3e8179..e544bba 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -137,7 +137,7 @@ fifo_open(ap) struct thread *td; struct fifoinfo *fip; struct pipe *fpipe; - int error; + int error, stops_deferred; vp = ap->a_vp; fp = ap->a_fp; @@ -188,8 +188,11 @@ fifo_open(ap) if ((ap->a_mode & O_NONBLOCK) == 0) { if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { VOP_UNLOCK(vp, 0); + stops_deferred = sigallowstop(); error = msleep(&fip->fi_readers, PIPE_MTX(fpipe), PDROP | PCATCH | PSOCK, "fifoor", 0); + if (stops_deferred) + sigdeferstop(); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) { fip->fi_readers--; @@ -212,8 +215,11 @@ fifo_open(ap) } if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { VOP_UNLOCK(vp, 0); + stops_deferred = sigallowstop(); error = msleep(&fip->fi_writers, PIPE_MTX(fpipe), PDROP | PCATCH | PSOCK, "fifoow", 0); + if (stops_deferred) + sigdeferstop(); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (error) { fip->fi_writers--; diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index cdb5f93..47a6ccf 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2596,15 +2596,18 @@ sigdeferstop(void) * not immediately suspend if a stop was posted. Instead, the thread * will suspend either via ast() or a subsequent interruptible sleep. */ -void -sigallowstop() +int +sigallowstop(void) { struct thread *td; + int prev; td = curthread; thread_lock(td); + prev = (td->td_flags & TDF_SBDRY) != 0; td->td_flags &= ~TDF_SBDRY; thread_unlock(td); + return (prev); } /* diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index f7fcaa9..f033702 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -325,7 +325,7 @@ extern struct mtx sigio_lock; int cursig(struct thread *td); int sigdeferstop(void); -void sigallowstop(void); +int sigallowstop(void); void execsigs(struct proc *p); void gsignal(int pgid, int sig, ksiginfo_t *ksi); void killproc(struct proc *p, char *why); |