summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-01-25 13:09:53 +0000
committerkib <kib@FreeBSD.org>2015-01-25 13:09:53 +0000
commit9ddc339f8bfb9d591096aa6d52debc019b7dbd06 (patch)
tree3bcdb13b4c31b879ba2265e39b65de7c88e20829
parent65e2f9460344e1eebe2ed160db1b56b96ab407fa (diff)
downloadFreeBSD-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.c8
-rw-r--r--sys/kern/kern_sig.c7
-rw-r--r--sys/sys/signalvar.h2
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);
OpenPOWER on IntegriCloud