Module Name:    src
Committed By:   dsl
Date:           Sun Dec 20 09:36:06 UTC 2009

Modified Files:
        src/sys/arch/xen/xen: xenevt.c
        src/sys/compat/svr4: svr4_net.c
        src/sys/compat/svr4_32: svr4_32_net.c
        src/sys/dev/dmover: dmover_io.c
        src/sys/dev/putter: putter.c
        src/sys/kern: kern_descrip.c kern_drvctl.c kern_event.c sys_mqueue.c
            sys_pipe.c sys_socket.c uipc_socket.c uipc_syscalls.c vfs_vnops.c
        src/sys/net: bpf.c if_tap.c
        src/sys/opencrypto: cryptodev.c
        src/sys/sys: file.h pipe.h socketvar.h

Log Message:
If a multithreaded app closes an fd while another thread is blocked in
read/write/accept, then the expectation is that the blocked thread will
exit and the close complete.
Since only one fd is affected, but many fd can refer to the same file,
the close code can only request the fs code unblock with ERESTART.
Fixed for pipes and sockets, ERESTART will only be generated after such
a close - so there should be no change for other programs.
Also rename fo_abort() to fo_restart() (this used to be fo_drain()).
Fixes PR/26567


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/xen/xen/xenevt.c
cvs rdiff -u -r1.57 -r1.58 src/sys/compat/svr4/svr4_net.c
cvs rdiff -u -r1.20 -r1.21 src/sys/compat/svr4_32/svr4_32_net.c
cvs rdiff -u -r1.36 -r1.37 src/sys/dev/dmover/dmover_io.c
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/putter/putter.c
cvs rdiff -u -r1.201 -r1.202 src/sys/kern/kern_descrip.c
cvs rdiff -u -r1.30 -r1.31 src/sys/kern/kern_drvctl.c
cvs rdiff -u -r1.67 -r1.68 src/sys/kern/kern_event.c
cvs rdiff -u -r1.28 -r1.29 src/sys/kern/sys_mqueue.c
cvs rdiff -u -r1.126 -r1.127 src/sys/kern/sys_pipe.c
cvs rdiff -u -r1.62 -r1.63 src/sys/kern/sys_socket.c
cvs rdiff -u -r1.195 -r1.196 src/sys/kern/uipc_socket.c
cvs rdiff -u -r1.137 -r1.138 src/sys/kern/uipc_syscalls.c
cvs rdiff -u -r1.167 -r1.168 src/sys/kern/vfs_vnops.c
cvs rdiff -u -r1.149 -r1.150 src/sys/net/bpf.c
cvs rdiff -u -r1.61 -r1.62 src/sys/net/if_tap.c
cvs rdiff -u -r1.50 -r1.51 src/sys/opencrypto/cryptodev.c
cvs rdiff -u -r1.69 -r1.70 src/sys/sys/file.h
cvs rdiff -u -r1.31 -r1.32 src/sys/sys/pipe.h
cvs rdiff -u -r1.122 -r1.123 src/sys/sys/socketvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/xenevt.c
diff -u src/sys/arch/xen/xen/xenevt.c:1.35 src/sys/arch/xen/xen/xenevt.c:1.36
--- src/sys/arch/xen/xen/xenevt.c:1.35	Wed Dec  9 21:32:58 2009
+++ src/sys/arch/xen/xen/xenevt.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*      $NetBSD: xenevt.c,v 1.35 2009/12/09 21:32:58 dsl Exp $      */
+/*      $NetBSD: xenevt.c,v 1.36 2009/12/20 09:36:05 dsl Exp $      */
 
 /*
  * Copyright (c) 2005 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.35 2009/12/09 21:32:58 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.36 2009/12/20 09:36:05 dsl Exp $");
 
 #include "opt_xen.h"
 #include <sys/param.h>
@@ -81,7 +81,7 @@
 	.fo_stat = fbadop_stat,
 	.fo_close = xenevt_fclose,
 	.fo_kqfilter = /* xenevt_fkqfilter */ fnullop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 dev_type_open(xenevtopen);

Index: src/sys/compat/svr4/svr4_net.c
diff -u src/sys/compat/svr4/svr4_net.c:1.57 src/sys/compat/svr4/svr4_net.c:1.58
--- src/sys/compat/svr4/svr4_net.c:1.57	Wed Dec  9 21:32:58 2009
+++ src/sys/compat/svr4/svr4_net.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: svr4_net.c,v 1.57 2009/12/09 21:32:58 dsl Exp $	*/
+/*	$NetBSD: svr4_net.c,v 1.58 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1994, 2008, 2009 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_net.c,v 1.57 2009/12/09 21:32:58 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_net.c,v 1.58 2009/12/20 09:36:05 dsl Exp $");
 
 #define COMPAT_SVR4 1
 
@@ -108,7 +108,7 @@
 	.fo_stat = soo_stat,
 	.fo_close = svr4_soo_close,
 	.fo_kqfilter = soo_kqfilter,
-	.fo_abort = soo_abort,
+	.fo_restart = soo_restart,
 };
 
 

Index: src/sys/compat/svr4_32/svr4_32_net.c
diff -u src/sys/compat/svr4_32/svr4_32_net.c:1.20 src/sys/compat/svr4_32/svr4_32_net.c:1.21
--- src/sys/compat/svr4_32/svr4_32_net.c:1.20	Wed Dec  9 21:32:58 2009
+++ src/sys/compat/svr4_32/svr4_32_net.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: svr4_32_net.c,v 1.20 2009/12/09 21:32:58 dsl Exp $	 */
+/*	$NetBSD: svr4_32_net.c,v 1.21 2009/12/20 09:36:05 dsl Exp $	 */
 
 /*-
  * Copyright (c) 1994, 2008, 2009 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_32_net.c,v 1.20 2009/12/09 21:32:58 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_32_net.c,v 1.21 2009/12/20 09:36:05 dsl Exp $");
 
 #define COMPAT_SVR4 1
 
@@ -102,7 +102,7 @@
 	.fo_poll = soo_poll,
 	.fo_stat = soo_stat,
 	.fo_close = svr4_soo_close,
-	.fo_abort = soo_abort,
+	.fo_restart = soo_restart,
 };
 
 

Index: src/sys/dev/dmover/dmover_io.c
diff -u src/sys/dev/dmover/dmover_io.c:1.36 src/sys/dev/dmover/dmover_io.c:1.37
--- src/sys/dev/dmover/dmover_io.c:1.36	Wed Dec  9 21:32:58 2009
+++ src/sys/dev/dmover/dmover_io.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: dmover_io.c,v 1.36 2009/12/09 21:32:58 dsl Exp $	*/
+/*	$NetBSD: dmover_io.c,v 1.37 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@@ -55,7 +55,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dmover_io.c,v 1.36 2009/12/09 21:32:58 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dmover_io.c,v 1.37 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/queue.h>
@@ -761,7 +761,7 @@
 	.fo_stat = dmio_stat,
 	.fo_close = dmio_close,
 	.fo_kqfilter = fnullop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 /*

Index: src/sys/dev/putter/putter.c
diff -u src/sys/dev/putter/putter.c:1.25 src/sys/dev/putter/putter.c:1.26
--- src/sys/dev/putter/putter.c:1.25	Wed Dec  9 21:32:59 2009
+++ src/sys/dev/putter/putter.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: putter.c,v 1.25 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: putter.c,v 1.26 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007  Antti Kantee.  All Rights Reserved.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: putter.c,v 1.25 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: putter.c,v 1.26 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -206,7 +206,7 @@
 	.fo_stat = putter_fop_stat,
 	.fo_close = putter_fop_close,
 	.fo_kqfilter = putter_fop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 static int

Index: src/sys/kern/kern_descrip.c
diff -u src/sys/kern/kern_descrip.c:1.201 src/sys/kern/kern_descrip.c:1.202
--- src/sys/kern/kern_descrip.c:1.201	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/kern_descrip.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_descrip.c,v 1.201 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: kern_descrip.c,v 1.202 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.201 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.202 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -610,7 +610,8 @@
 		 * Wait for other references to drain.  This is typically
 		 * an application error - the descriptor is being closed
 		 * while still in use.
-		 *
+		 * (Or just a threaded application trying to unblock its
+		 * thread that sleeps in (say) accept()).
 		 */
 		atomic_or_uint(&ff->ff_refcnt, FR_CLOSING);
 
@@ -623,8 +624,15 @@
 			knote_fdclose(fd);
 		}
 
-		/* Try to drain out descriptor references. */
-		(*fp->f_ops->fo_abort)(fp);
+		/*
+		 * Since the file system code doesn't know which fd
+		 * each request came from (think dup()), we have to
+		 * ask it to return ERESTART for any long-term blocks.
+		 * The re-entry through read/write/etc will detect the
+		 * closed fd and return EBAFD.
+		 * Blocked partial writes may return a short length.
+		 */
+		(*fp->f_ops->fo_restart)(fp);
 		mutex_enter(&fdp->fd_lock);
 
 		/*
@@ -632,6 +640,8 @@
 		 * in order to ensure that all pre-existing references
 		 * have been drained.  New references past this point are
 		 * of no interest.
+		 * XXX (dsl) this may need to call fo_restart() after a
+		 * timeout to guarantee that all the system calls exit.
 		 */
 		while ((ff->ff_refcnt & FR_MASK) != 0) {
 			cv_wait(&ff->ff_closing, &fdp->fd_lock);
@@ -1787,7 +1797,7 @@
 }
 
 void
-fnullop_abort(file_t *fp)
+fnullop_restart(file_t *fp)
 {
 
 }

Index: src/sys/kern/kern_drvctl.c
diff -u src/sys/kern/kern_drvctl.c:1.30 src/sys/kern/kern_drvctl.c:1.31
--- src/sys/kern/kern_drvctl.c:1.30	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/kern_drvctl.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_drvctl.c,v 1.30 2009/12/09 21:32:59 dsl Exp $ */
+/* $NetBSD: kern_drvctl.c,v 1.31 2009/12/20 09:36:05 dsl Exp $ */
 
 /*
  * Copyright (c) 2004
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_drvctl.c,v 1.30 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_drvctl.c,v 1.31 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,7 +90,7 @@
 	.fo_stat = drvctl_stat,
 	.fo_close = drvctl_close,
 	.fo_kqfilter = fnullop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 #define MAXLOCATORS 100

Index: src/sys/kern/kern_event.c
diff -u src/sys/kern/kern_event.c:1.67 src/sys/kern/kern_event.c:1.68
--- src/sys/kern/kern_event.c:1.67	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/kern_event.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_event.c,v 1.67 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: kern_event.c,v 1.68 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.67 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.68 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -115,7 +115,7 @@
 	.fo_stat = kqueue_stat,
 	.fo_close = kqueue_close,
 	.fo_kqfilter = kqueue_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 static const struct filterops kqread_filtops =

Index: src/sys/kern/sys_mqueue.c
diff -u src/sys/kern/sys_mqueue.c:1.28 src/sys/kern/sys_mqueue.c:1.29
--- src/sys/kern/sys_mqueue.c:1.28	Thu Dec 10 12:22:48 2009
+++ src/sys/kern/sys_mqueue.c	Sun Dec 20 09:36:05 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_mqueue.c,v 1.28 2009/12/10 12:22:48 drochner Exp $	*/
+/*	$NetBSD: sys_mqueue.c,v 1.29 2009/12/20 09:36:05 dsl Exp $	*/
 
 /*
  * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.28 2009/12/10 12:22:48 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.29 2009/12/20 09:36:05 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -103,7 +103,7 @@
 	.fo_stat = mq_stat_fop,
 	.fo_close = mq_close_fop,
 	.fo_kqfilter = fnullop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 static const struct syscall_package mqueue_syscalls[] = {

Index: src/sys/kern/sys_pipe.c
diff -u src/sys/kern/sys_pipe.c:1.126 src/sys/kern/sys_pipe.c:1.127
--- src/sys/kern/sys_pipe.c:1.126	Tue Dec 15 18:35:18 2009
+++ src/sys/kern/sys_pipe.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_pipe.c,v 1.126 2009/12/15 18:35:18 dsl Exp $	*/
+/*	$NetBSD: sys_pipe.c,v 1.127 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.126 2009/12/15 18:35:18 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.127 2009/12/20 09:36:06 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -109,7 +109,7 @@
 static int	pipe_kqfilter(file_t *, struct knote *);
 static int	pipe_stat(file_t *, struct stat *);
 static int	pipe_ioctl(file_t *, u_long, void *);
-static void	pipe_abort(file_t *);
+static void	pipe_restart(file_t *);
 
 static const struct fileops pipeops = {
 	.fo_read = pipe_read,
@@ -120,7 +120,7 @@
 	.fo_stat = pipe_stat,
 	.fo_close = pipe_close,
 	.fo_kqfilter = pipe_kqfilter,
-	.fo_abort = pipe_abort,
+	.fo_restart = pipe_restart,
 };
 
 /*
@@ -449,7 +449,7 @@
 	size_t nread = 0;
 	size_t size;
 	size_t ocnt;
-	int slept = 0;
+	unsigned int wakeup_state = 0;
 
 	mutex_enter(lock);
 	++rpipe->pipe_busy;
@@ -579,7 +579,7 @@
 		cv_broadcast(&rpipe->pipe_wcv);
 #endif
 
-		if (slept) {
+		if (wakeup_state & PIPE_RESTART) {
 			error = ERESTART;
 			goto unlocked_error;
 		}
@@ -588,7 +588,7 @@
 		error = cv_wait_sig(&rpipe->pipe_rcv, lock);
 		if (error != 0)
 			goto unlocked_error;
-		slept = 1;
+		wakeup_state = rpipe->pipe_state;
 		goto again;
 	}
 
@@ -599,6 +599,7 @@
 unlocked_error:
 	--rpipe->pipe_busy;
 	if (rpipe->pipe_busy == 0) {
+		rpipe->pipe_state &= ~PIPE_RESTART;
 		cv_broadcast(&rpipe->pipe_draincv);
 	}
 	if (bp->cnt < MINPIPESIZE) {
@@ -823,7 +824,7 @@
 	struct pipebuf *bp;
 	kmutex_t *lock;
 	int error;
-	int slept = 0;
+	unsigned int wakeup_state = 0;
 
 	/* We want to write to our peer */
 	rpipe = (struct pipe *) fp->f_data;
@@ -846,6 +847,7 @@
 	if ((error = pipelock(wpipe, 1)) != 0) {
 		--wpipe->pipe_busy;
 		if (wpipe->pipe_busy == 0) {
+			wpipe->pipe_state &= ~PIPE_RESTART;
 			cv_broadcast(&wpipe->pipe_draincv);
 		}
 		mutex_exit(lock);
@@ -976,6 +978,7 @@
 
 			bp->cnt += size;
 			KASSERT(bp->cnt <= bp->size);
+			wakeup_state = 0;
 		} else {
 			/*
 			 * If the "read-side" has been blocked, wake it up now.
@@ -997,12 +1000,10 @@
 			if (bp->cnt)
 				pipeselwakeup(wpipe, wpipe, POLL_IN);
 
-#if 0 /* I think some programs don't like the partial write... */
-			if (slept) {
+			if (wakeup_state & PIPE_RESTART) {
 				error = ERESTART;
 				break;
 			}
-#endif
 
 			pipeunlock(wpipe);
 			error = cv_wait_sig(&wpipe->pipe_wcv, lock);
@@ -1017,12 +1018,13 @@
 				error = EPIPE;
 				break;
 			}
-			slept = 1;
+			wakeup_state = wpipe->pipe_state;
 		}
 	}
 
 	--wpipe->pipe_busy;
 	if (wpipe->pipe_busy == 0) {
+		wpipe->pipe_state &= ~PIPE_RESTART;
 		cv_broadcast(&wpipe->pipe_draincv);
 	}
 	if (bp->cnt > 0) {
@@ -1223,18 +1225,19 @@
 }
 
 static void
-pipe_abort(file_t *fp)
+pipe_restart(file_t *fp)
 {
 	struct pipe *pipe = fp->f_data;
 
 	/*
 	 * Unblock blocked reads/writes in order to allow close() to complete.
-	 * This isn't going to work yet!
-	 * The underlying problem is that only the 'fd' in question needs
-	 * its operations terminating, the pipe itself my be open via
-	 * other fd.
+	 * System calls return ERESTART so that the fd is revalidated.
+	 * (Partial writes return the transfer length.)
 	 */
 	mutex_enter(pipe->pipe_lock);
+	pipe->pipe_state |= PIPE_RESTART;
+	/* Wakeup both cvs, maybe we only need one, but maybe there are some
+	 * other paths where wakeup is needed, and it saves deciding which! */
 	cv_broadcast(&pipe->pipe_rcv);
 	cv_broadcast(&pipe->pipe_wcv);
 	mutex_exit(pipe->pipe_lock);

Index: src/sys/kern/sys_socket.c
diff -u src/sys/kern/sys_socket.c:1.62 src/sys/kern/sys_socket.c:1.63
--- src/sys/kern/sys_socket.c:1.62	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/sys_socket.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_socket.c,v 1.62 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: sys_socket.c,v 1.63 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_socket.c,v 1.62 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_socket.c,v 1.63 2009/12/20 09:36:06 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -89,7 +89,7 @@
 	.fo_stat = soo_stat,
 	.fo_close = soo_close,
 	.fo_kqfilter = soo_kqfilter,
-	.fo_abort = soo_abort,
+	.fo_restart = soo_restart,
 };
 
 /* ARGSUSED */
@@ -260,8 +260,8 @@
 }
 
 void
-soo_abort(file_t *fp)
+soo_restart(file_t *fp)
 {
 
-	soabortop(fp->f_data);
+	sorestart(fp->f_data);
 }

Index: src/sys/kern/uipc_socket.c
diff -u src/sys/kern/uipc_socket.c:1.195 src/sys/kern/uipc_socket.c:1.196
--- src/sys/kern/uipc_socket.c:1.195	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/uipc_socket.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_socket.c,v 1.195 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: uipc_socket.c,v 1.196 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.195 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.196 2009/12/20 09:36:06 dsl Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_sock_counters.h"
@@ -905,6 +905,7 @@
 	struct proc	*p;
 	long		space, len, resid, clen, mlen;
 	int		error, s, dontroute, atomic;
+	short		wakeup_state = 0;
 
 	p = l->l_proc;
 	sodopendfree();
@@ -979,11 +980,17 @@
 				goto release;
 			}
 			sbunlock(&so->so_snd);
+			if (wakeup_state & SS_RESTARTSYS) {
+				error = ERESTART;
+				goto out;
+			}
 			error = sbwait(&so->so_snd);
 			if (error)
 				goto out;
+			wakeup_state = so->so_state;
 			goto restart;
 		}
+		wakeup_state = 0;
 		mp = &top;
 		space -= clen;
 		do {
@@ -1159,6 +1166,7 @@
 	struct mbuf	*nextrecord;
 	int		mbuf_removed = 0;
 	const struct domain *dom;
+	short		wakeup_state = 0;
 
 	pr = so->so_proto;
 	atomic = pr->pr_flags & PR_ATOMIC;
@@ -1273,12 +1281,16 @@
 		SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
 		SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
 		sbunlock(&so->so_rcv);
-		error = sbwait(&so->so_rcv);
+		if (wakeup_state & SS_RESTARTSYS)
+			error = ERESTART;
+		else
+			error = sbwait(&so->so_rcv);
 		if (error != 0) {
 			sounlock(so);
 			splx(s);
 			return error;
 		}
+		wakeup_state = so->so_state;
 		goto restart;
 	}
  dontblock:
@@ -1417,6 +1429,7 @@
 			panic("receive 3");
 #endif
 		so->so_state &= ~SS_RCVATMARK;
+		wakeup_state = 0;
 		len = uio->uio_resid;
 		if (so->so_oobmark && len > so->so_oobmark - offset)
 			len = so->so_oobmark - offset;
@@ -1549,7 +1562,10 @@
 				    NULL, (struct mbuf *)(long)flags, NULL, l);
 			SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
 			SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
-			error = sbwait(&so->so_rcv);
+			if (wakeup_state & SS_RESTARTSYS)
+				error = ERESTART;
+			else
+				error = sbwait(&so->so_rcv);
 			if (error != 0) {
 				sbunlock(&so->so_rcv);
 				sounlock(so);
@@ -1558,6 +1574,7 @@
 			}
 			if ((m = so->so_rcv.sb_mb) != NULL)
 				nextrecord = m->m_nextpkt;
+			wakeup_state = so->so_state;
 		}
 	}
 
@@ -1625,15 +1642,22 @@
 }
 
 void
-soabortop(struct socket *so)
+sorestart(struct socket *so)
 {
-#if 0   /* ad@ wrote this, then disabled it as 'not working' */
+	/*
+	 * An application has called close() on an fd on which another
+	 * of its threads has called a socket system call.
+	 * Mark this and wake everyone up, and code that would block again
+	 * instead returns ERESTART.
+	 * On system call re-entry the fd is validated and EBADF returned.
+	 * Any other fd will block again on the 2nd syscall.
+	 */
 	solock(so);
-	so->so_state |= SS_ISABORTING;
+	so->so_state |= SS_RESTARTSYS;
 	cv_broadcast(&so->so_cv);
-	soshutdown(so, SHUT_RDWR);
+	cv_broadcast(&so->so_snd.sb_cv);
+	cv_broadcast(&so->so_rcv.sb_cv);
 	sounlock(so);
-#endif
 }
 
 void

Index: src/sys/kern/uipc_syscalls.c
diff -u src/sys/kern/uipc_syscalls.c:1.137 src/sys/kern/uipc_syscalls.c:1.138
--- src/sys/kern/uipc_syscalls.c:1.137	Wed Dec  9 21:33:00 2009
+++ src/sys/kern/uipc_syscalls.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_syscalls.c,v 1.137 2009/12/09 21:33:00 dsl Exp $	*/
+/*	$NetBSD: uipc_syscalls.c,v 1.138 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.137 2009/12/09 21:33:00 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.138 2009/12/20 09:36:06 dsl Exp $");
 
 #include "opt_pipe.h"
 
@@ -170,6 +170,7 @@
 	struct mbuf	*nam;
 	int		error, fd;
 	struct socket	*so, *so2;
+	short		wakeup_state = 0;
 
 	if ((fp = fd_getfile(sock)) == NULL)
 		return (EBADF);
@@ -202,10 +203,15 @@
 			so->so_error = ECONNABORTED;
 			break;
 		}
+		if (wakeup_state & SS_RESTARTSYS) {
+			error = ERESTART;
+			goto bad;
+		}
 		error = sowait(so, true, 0);
 		if (error) {
 			goto bad;
 		}
+		wakeup_state = so->so_state;
 	}
 	if (so->so_error) {
 		error = so->so_error;

Index: src/sys/kern/vfs_vnops.c
diff -u src/sys/kern/vfs_vnops.c:1.167 src/sys/kern/vfs_vnops.c:1.168
--- src/sys/kern/vfs_vnops.c:1.167	Wed Dec  9 21:32:59 2009
+++ src/sys/kern/vfs_vnops.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnops.c,v 1.167 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: vfs_vnops.c,v 1.168 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.167 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.168 2009/12/20 09:36:06 dsl Exp $");
 
 #include "veriexec.h"
 
@@ -122,7 +122,7 @@
 	.fo_stat = vn_statfile,
 	.fo_close = vn_closefile,
 	.fo_kqfilter = vn_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 /*

Index: src/sys/net/bpf.c
diff -u src/sys/net/bpf.c:1.149 src/sys/net/bpf.c:1.150
--- src/sys/net/bpf.c:1.149	Wed Dec  9 21:32:59 2009
+++ src/sys/net/bpf.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: bpf.c,v 1.149 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: bpf.c,v 1.150 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.149 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.150 2009/12/20 09:36:06 dsl Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_bpf.h"
@@ -165,7 +165,7 @@
 	.fo_stat = bpf_stat,
 	.fo_close = bpf_close,
 	.fo_kqfilter = bpf_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 dev_type_open(bpfopen);

Index: src/sys/net/if_tap.c
diff -u src/sys/net/if_tap.c:1.61 src/sys/net/if_tap.c:1.62
--- src/sys/net/if_tap.c:1.61	Wed Dec  9 21:32:59 2009
+++ src/sys/net/if_tap.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_tap.c,v 1.61 2009/12/09 21:32:59 dsl Exp $	*/
+/*	$NetBSD: if_tap.c,v 1.62 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*
  *  Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation.
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.61 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.62 2009/12/20 09:36:06 dsl Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "bpfilter.h"
@@ -161,7 +161,7 @@
 	.fo_stat = tap_fops_stat,
 	.fo_close = tap_fops_close,
 	.fo_kqfilter = tap_fops_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 /* Helper for cloning open() */

Index: src/sys/opencrypto/cryptodev.c
diff -u src/sys/opencrypto/cryptodev.c:1.50 src/sys/opencrypto/cryptodev.c:1.51
--- src/sys/opencrypto/cryptodev.c:1.50	Wed Dec  9 21:32:59 2009
+++ src/sys/opencrypto/cryptodev.c	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: cryptodev.c,v 1.50 2009/12/09 21:32:59 dsl Exp $ */
+/*	$NetBSD: cryptodev.c,v 1.51 2009/12/20 09:36:06 dsl Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $	*/
 /*	$OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $	*/
 
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.50 2009/12/09 21:32:59 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.51 2009/12/20 09:36:06 dsl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -157,7 +157,7 @@
 	.fo_stat = cryptof_stat,
 	.fo_close = cryptof_close,
 	.fo_kqfilter = fnullop_kqfilter,
-	.fo_abort = fnullop_abort,
+	.fo_restart = fnullop_restart,
 };
 
 struct csession *cryptodev_csefind(struct fcrypt *, u_int);

Index: src/sys/sys/file.h
diff -u src/sys/sys/file.h:1.69 src/sys/sys/file.h:1.70
--- src/sys/sys/file.h:1.69	Wed Dec  9 21:33:00 2009
+++ src/sys/sys/file.h	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: file.h,v 1.69 2009/12/09 21:33:00 dsl Exp $	*/
+/*	$NetBSD: file.h,v 1.70 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
 		int	(*fo_stat)	(struct file *, struct stat *);
 		int	(*fo_close)	(struct file *);
 		int	(*fo_kqfilter)	(struct file *, struct knote *);
-		void	(*fo_abort)	(struct file *);
+		void	(*fo_restart)	(struct file *);
 		void	(*fo_spare1)	(void);
 		void	(*fo_spare2)	(void);
 	} *f_ops;
@@ -162,7 +162,7 @@
 int	fbadop_ioctl(struct file *, u_long, void *);
 int	fbadop_close(struct file *);
 int	fbadop_stat(struct file *, struct stat *);
-void	fnullop_abort(struct file *);
+void	fnullop_restart(struct file *);
 
 #endif /* _KERNEL */
 

Index: src/sys/sys/pipe.h
diff -u src/sys/sys/pipe.h:1.31 src/sys/sys/pipe.h:1.32
--- src/sys/sys/pipe.h:1.31	Sun Dec 13 18:27:02 2009
+++ src/sys/sys/pipe.h	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: pipe.h,v 1.31 2009/12/13 18:27:02 dsl Exp $ */
+/* $NetBSD: pipe.h,v 1.32 2009/12/20 09:36:06 dsl Exp $ */
 
 /*
  * Copyright (c) 1996 John S. Dyson
@@ -96,6 +96,7 @@
 				   pointers/data. */
 #define	PIPE_LWANT	0x200	/* Process wants exclusive access to
 				   pointers/data. */
+#define	PIPE_RESTART	0x400	/* Return ERESTART to blocked syscalls */
 
 /*
  * Per-pipe data structure.

Index: src/sys/sys/socketvar.h
diff -u src/sys/sys/socketvar.h:1.122 src/sys/sys/socketvar.h:1.123
--- src/sys/sys/socketvar.h:1.122	Wed Dec  9 21:33:00 2009
+++ src/sys/sys/socketvar.h	Sun Dec 20 09:36:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: socketvar.h,v 1.122 2009/12/09 21:33:00 dsl Exp $	*/
+/*	$NetBSD: socketvar.h,v 1.123 2009/12/20 09:36:06 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -199,6 +199,7 @@
 #define	SS_CANTRCVMORE		0x020	/* can't receive more data from peer */
 #define	SS_RCVATMARK		0x040	/* at mark on input */
 #define	SS_ISABORTING		0x080	/* aborting fd references - close() */
+#define	SS_RESTARTSYS		0x100	/* restart blocked system calls */
 #define	SS_ISDISCONNECTED	0x800	/* socket disconnected from peer */
 
 #define	SS_ASYNC		0x100	/* async i/o notify */
@@ -256,7 +257,7 @@
 int	soo_kqfilter(file_t *, struct knote *);
 int 	soo_close(file_t *);
 int	soo_stat(file_t *, struct stat *);
-void	soo_abort(file_t *);
+void	soo_restart(file_t *);
 void	sbappend(struct sockbuf *, struct mbuf *);
 void	sbappendstream(struct sockbuf *, struct mbuf *);
 int	sbappendaddr(struct sockbuf *, const struct sockaddr *, struct mbuf *,
@@ -313,7 +314,7 @@
 int	sosetopt(struct socket *, struct sockopt *);
 int	so_setsockopt(struct lwp *, struct socket *, int, int, const void *, size_t);
 int	soshutdown(struct socket *, int);
-void	soabortop(struct socket *);
+void	sorestart(struct socket *);
 void	sowakeup(struct socket *, struct sockbuf *, int);
 int	sockargs(struct mbuf **, const void *, size_t, int);
 int	sopoll(struct socket *, int);

Reply via email to