Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Apr 2017 17:23:28 +0000 (UTC)
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r316874 - head/sys/kern
Message-ID:  <201704141723.v3EHNS3B043902@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sobomax
Date: Fri Apr 14 17:23:28 2017
New Revision: 316874
URL: https://svnweb.freebsd.org/changeset/base/316874

Log:
  Restore ability to shutdown DGRAM sockets, still forcing ENOTCONN to be returned
  by the shutdown(2) system call. This ability has been lost as part of the svn
  revision 285910.
  
  Reviewed by:	ed, rwatson, glebius, hiren
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D10351

Modified:
  head/sys/kern/uipc_socket.c

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Fri Apr 14 17:22:54 2017	(r316873)
+++ head/sys/kern/uipc_socket.c	Fri Apr 14 17:23:28 2017	(r316874)
@@ -2343,13 +2343,27 @@ int
 soshutdown(struct socket *so, int how)
 {
 	struct protosw *pr = so->so_proto;
-	int error;
+	int error, soerror_enotconn;
 
 	if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
 		return (EINVAL);
+
+	soerror_enotconn = 0;
 	if ((so->so_state &
-	    (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0)
-		return (ENOTCONN);
+	    (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
+		/*
+		 * POSIX mandates us to return ENOTCONN when shutdown(2) is
+		 * invoked on a datagram sockets, however historically we would
+		 * actually tear socket down. This is known to be leveraged by
+		 * some applications to unblock process waiting in recvXXX(2)
+		 * by other process that it shares that socket with. Try to meet
+		 * both backward-compatibility and POSIX requirements by forcing
+		 * ENOTCONN but still asking protocol to perform pru_shutdown().
+		 */
+		if (so->so_type != SOCK_DGRAM)
+			return (ENOTCONN);
+		soerror_enotconn = 1;
+	}
 
 	CURVNET_SET(so->so_vnet);
 	if (pr->pr_usrreqs->pru_flush != NULL)
@@ -2360,11 +2374,12 @@ soshutdown(struct socket *so, int how)
 		error = (*pr->pr_usrreqs->pru_shutdown)(so);
 		wakeup(&so->so_timeo);
 		CURVNET_RESTORE();
-		return (error);
+		return ((error == 0 && soerror_enotconn) ? ENOTCONN : error);
 	}
 	wakeup(&so->so_timeo);
 	CURVNET_RESTORE();
-	return (0);
+
+	return (soerror_enotconn ? ENOTCONN : 0);
 }
 
 void



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