Skip to content

Conversation

@julianz-
Copy link
Contributor

@julianz- julianz- commented Oct 31, 2025

Adds a more robust error-handling mechanism to the PyOpenSSL SSLConnection wrapper to better manage exceptions raised during connection shutdown and close operations.

The pyopenssl.py module now includes the context manager, _morph_syscall_to_connection_error, to wrap error-prone methods. This context manager intercepts low-level OpenSSL.SSL.SysCallError exceptions and translates them into standard Python exception types (e.g., ConnectionAbortedError, BrokenPipeError, ConnectionRefusedError, etc.) based on the underlying errno code.

Why this is useful: Currently, when a connection fails due to a system event (like a remote peer abruptly closing the socket), the resulting SysCallError can be difficult to catch and handle cleanly in application code.

This change ensures that applications using Cheroot can reliably catch a standard ConnectionError or one of its subclasses, improving the robustness and usability of the SSL connection handling.


This change is Reviewable

@codecov
Copy link

codecov bot commented Oct 31, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.32%. Comparing base (4a8dc43) to head (85afc8e).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #786      +/-   ##
==========================================
+ Coverage   79.30%   79.32%   +0.02%     
==========================================
  Files          29       30       +1     
  Lines        4203     4237      +34     
  Branches      539      539              
==========================================
+ Hits         3333     3361      +28     
- Misses        728      730       +2     
- Partials      142      146       +4     

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is ok now?

@julianz- julianz- force-pushed the pyopenssl-error-translation branch 3 times, most recently from e2f0a3b to b594cd5 Compare October 31, 2025 20:37
@julianz- julianz- force-pushed the pyopenssl-error-translation branch 3 times, most recently from cbc0181 to 4444f9d Compare November 1, 2025 00:51
Comment on lines 273 to 275
# translate any SysCallError to ConnectionError
with _morph_syscall_to_connection_error(method):
return getattr(self._ssl_conn, method)(*new_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is one way of solving that.. we could do so for now. Although, I'd be good to get rid of SSLConnectionProxyMeta in some future iteration/PR. I've always found this metaclass patching confusing and wanted to simplify it if possible.

Copy link
Contributor Author

@julianz- julianz- Nov 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried refactoring to remove the metaclass and I think it works but will add as a new PR.

@webknjaz webknjaz changed the title Map PyOpenSSL SysCallErrors to standard Python ConnectionErrors Re-raise PyOpenSSL SysCallErrors as respective errno-mapped standard Python ConnectionError subclasses Nov 1, 2025
@julianz- julianz- force-pushed the pyopenssl-error-translation branch from 4444f9d to 8dc9dc5 Compare November 1, 2025 01:25
@julianz- julianz- force-pushed the pyopenssl-error-translation branch 5 times, most recently from f691222 to b1308b5 Compare November 1, 2025 03:01

# Create SSLConnection object. The patched SSL.Connection() call returns
# a mock that is stored internally as conn._ssl_conn.
conn = SSLConnection(mock_ssl_context)

Check failure

Code scanning / CodeQL

Non-callable called Error test

Call to a
non-callable
of
class SSLConnectionProxyMeta
.
@julianz- julianz- force-pushed the pyopenssl-error-translation branch 2 times, most recently from 1dabdf8 to b768b11 Compare November 1, 2025 03:07
@julianz- julianz- force-pushed the pyopenssl-error-translation branch 2 times, most recently from bf8e9e0 to e9a31db Compare November 1, 2025 03:46
PyOpenSSL raises SysCallError which cheroot does not translate, leading to
unhandled exceptions when the underlying connection is closed or shut down
abruptly. This commit ensures all relevant errno codes are translated into
standard Python ConnectionError types for reliable handling by consumers.
@julianz- julianz- force-pushed the pyopenssl-error-translation branch 2 times, most recently from 85afc8e to a26fd31 Compare November 1, 2025 05:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants