When you develop on OS X, and start Plone 5.2 in foreground with PDBDebugMode activated, you ocassionally can see the following error:
2021-02-11 22:58:18,907 ERROR [waitress:121][MainThread] Socket error
Traceback (most recent call last):
File "/Users/fred/.buildout/eggs/waitress-1.4.4-py3.8.egg/waitress/channel.py", line 118, in handle_write
flush()
File "/Users/fred/.buildout/eggs/waitress-1.4.4-py3.8.egg/waitress/channel.py", line 227, in _flush_some
num_sent = self.send(chunk)
File "/Users/fred/.buildout/eggs/waitress-1.4.4-py3.8.egg/waitress/wasyncore.py", line 433, in send
result = self.socket.send(data)
OSError: [Errno 41] Protocol wrong type for socket
[Errno 41] Protocol wrong type for socket
Which is very annoying because it seems to be random and it throws you into a pdb where you have to continue first to get started. It's easy to ignore, but still mosquito iritating, you keep waving your hands :-(. I did some searching yesterday and it's reported by other communities as well, not limited to Python, but specific for OS X
The most thorough explanation IMHO was written by a Rust developer in 2014:
http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
If I understand his blog post correctly its an edge case where OS X return a wrong code when a socket is being closed but some data is still sent. His solution in Rust at the end of the article is something I think we can apply 1:1 to Python/Waitress.
It's this method in waitress wasyncore.py:
If you import EPROTOTYPE as well from errno (imports at the top of wasyncore.py) and add the two commented lines below, you just ignore it.
Maybe instead of pass
, return 0
would be better. After I added this locally, the random Pdb's so far have stopped.
def send(self, data):
try:
result = self.socket.send(data)
return result
except socket.error as why:
if why.args[0] == EWOULDBLOCK:
return 0
elif why.args[0] in _DISCONNECTED:
self.handle_close()
return 0
#elif why.args[0] == EPROTOTYPE:
# pass
else:
raise