-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
asyncio: StreamWriter write_eof() after close raises mysterious AttributeError #75828
Comments
Currently, if one attempts to do write_eof() on a StreamWriter after the underlying transport is already closed, an AttributeError is raised: Traceback (most recent call last):
File "<snip>\scratch_3.py", line 34, in main_coro
writer.write_eof()
File "C:\Program Files\Python36\lib\asyncio\streams.py", line 300, in write_eof
return self._transport.write_eof()
File "C:\Program Files\Python36\lib\asyncio\selector_events.py", line 808, in write_eof
self._sock.shutdown(socket.SHUT_WR)
AttributeError: 'NoneType' object has no attribute 'shutdown' This is because _SelectorSocketTransport.write_eof() only checks for self._eof before calling self._sock.shutdown(), and self._sock has already been assigned None after _call_connection_lost(). Compare with StreamWriter.write() after close, which either does nothing or logs a warning after 5 attempts; or StreamWriter.drain() after close, which raises a ConnectionResetError; or even StreamWriter.close() after close, which does nothing. Trying to do write_eof() after close may happen unintentionally, for example when the following sequence of events happen:
Currently the only way to handle this gracefully is to either catch AttributeError or check StreamWriter.transport.is_closing() before write_eof(). Neither is pretty. I suggest making write_eof() after close either do nothing, or raise a subclass of ConnectionError. Both will be easier to handle then the current behavior. Attached repro. |
This issue is somewhat related to bpo-27223, in that both are caused by using self._sock after it has already been assigned None when the connection is closed. It seems like Transports in general may need better protection from this kind of behavior. |
(Sorry, I don't work on asyncio anymore.) |
If this issue isn't yet fixed could you please submit a PR? |
I was about to write a long comment asking what the appropriate behavior should be, but then saw that _ProactorSocketTransport already handles the same issue properly, so I will just change _SelectorSocketTransport to do the same thing. |
Merged, thanks for looking into this! BTW, if you have any other bugfixes in mind, today is pretty much last chance to get them into 3.7.0 |
Would be great to have this change in 3.7.0 (it's safe to merge it IMO) |
Turns out my typo when preparing the pull request had another victim: the changelog entries in documentation currently links to the wrong issue. I'll make a PR to fix that typo; since it's just documentation, hopefully it can still get into Python 3.6.6 and 3.7.0. |
Well, I opened the PR, it shows up here, but there's no reviewer assigned. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: