Commit 7fa0f290 authored by Jay Oster's avatar Jay Oster

Fix EPROTOTYPE race condition on macOS [supersedes #1033]

parent 778b8f44
...@@ -322,7 +322,7 @@ class socket(object): ...@@ -322,7 +322,7 @@ class socket(object):
try: try:
return sock.send(data, flags) return sock.send(data, flags)
except error as ex: except error as ex:
if ex.args[0] != EWOULDBLOCK or timeout == 0.0: if ex.args[0] not in _socketcommon.GSENDAGAIN or timeout == 0.0:
raise raise
sys.exc_clear() sys.exc_clear()
self._wait(self._write_event) self._wait(self._write_event)
......
...@@ -389,7 +389,7 @@ class socket(object): ...@@ -389,7 +389,7 @@ class socket(object):
try: try:
return _socket.socket.send(self._sock, data, flags) return _socket.socket.send(self._sock, data, flags)
except error as ex: except error as ex:
if ex.args[0] != EWOULDBLOCK or timeout == 0.0: if ex.args[0] not in _socketcommon.GSENDAGAIN or timeout == 0.0:
raise raise
self._wait(self._write_event) self._wait(self._write_event)
try: try:
......
...@@ -78,6 +78,8 @@ from gevent._util import copy_globals ...@@ -78,6 +78,8 @@ from gevent._util import copy_globals
from gevent._util import _NONE from gevent._util import _NONE
is_windows = sys.platform == 'win32' is_windows = sys.platform == 'win32'
is_macos = sys.platform == 'darwin'
# pylint:disable=no-name-in-module,unused-import # pylint:disable=no-name-in-module,unused-import
if is_windows: if is_windows:
# no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN # no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN
...@@ -102,6 +104,17 @@ try: ...@@ -102,6 +104,17 @@ try:
except ImportError: except ImportError:
EBADF = 9 EBADF = 9
# macOS can return EPROTOTYPE when writing to a socket that is shutting
# Down. Retrying the write should return the expected EPIPE error.
# Downstream classes (like pywsgi) know how to handle/ignore EPIPE.
# This set is used by socket.send() to decide whether the write should
# be retried. The default is to retry only on EWOULDBLOCK. Here we add
# EPROTOTYPE on macOS to handle this platform-specific race condition.
GSENDAGAIN = (EWOULDBLOCK,)
if is_macos:
from errno import EPROTOTYPE
GSENDAGAIN += (EPROTOTYPE,)
import _socket import _socket
_realsocket = _socket.socket _realsocket = _socket.socket
import socket as __socket__ import socket as __socket__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment