diff -r a218260334c4 Lib/test/test_socket.py --- a/Lib/test/test_socket.py Tue Oct 18 15:48:14 2016 +0200 +++ b/Lib/test/test_socket.py Tue Oct 18 15:46:06 2016 -0400 @@ -4552,6 +4552,18 @@ self.assertTrue(issubclass(socket.gaierror, OSError)) self.assertTrue(issubclass(socket.timeout, OSError)) + def test_setblocking_invalidfd(self): + # Regression test for issue #28471 + + sock0 = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + sock = socket.socket( + socket.AF_INET, socket.SOCK_STREAM, 0, sock0.fileno()) + sock0.close() + + with self.assertRaises(OSError): + sock.setblocking(False) + + @unittest.skipUnless(sys.platform == 'linux', 'Linux specific test') class TestLinuxAbstractNamespace(unittest.TestCase): diff -r a218260334c4 Modules/socketmodule.c --- a/Modules/socketmodule.c Tue Oct 18 15:48:14 2016 +0200 +++ b/Modules/socketmodule.c Tue Oct 18 15:46:06 2016 -0400 @@ -622,6 +622,7 @@ static int internal_setblocking(PySocketSockObject *s, int block) { + int result = -1; #ifdef MS_WINDOWS u_long arg; #endif @@ -641,34 +642,39 @@ #if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)) block = !block; if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1) - goto error; + goto done; #else delay_flag = fcntl(s->sock_fd, F_GETFL, 0); if (delay_flag == -1) - goto error; + goto done; if (block) new_delay_flag = delay_flag & (~O_NONBLOCK); else new_delay_flag = delay_flag | O_NONBLOCK; if (new_delay_flag != delay_flag) if (fcntl(s->sock_fd, F_SETFL, new_delay_flag) == -1) - goto error; + goto done; #endif #else /* MS_WINDOWS */ arg = !block; if (ioctlsocket(s->sock_fd, FIONBIO, &arg) != 0) - goto error; + goto done; #endif /* MS_WINDOWS */ + + result = 0; + + done: Py_END_ALLOW_THREADS - return 0; - error: + if (result) { #ifndef MS_WINDOWS - PyErr_SetFromErrno(PyExc_OSError); + PyErr_SetFromErrno(PyExc_OSError); #else - PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); -#endif - return -1; + PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); +#endif + } + + return result; } static int