qa: Account for unset errno in ConnectionResetError #33875

pull hodlinator wants to merge 1 commits into bitcoin:master from hodlinator:2025/11/RemoteDisconnect_err changing 1 files +9 βˆ’4
  1. hodlinator commented at 9:10 pm on November 14, 2025: contributor

    The lack of errno can cause unclear and long log output.

    Issue can be triggered by:

    0--- a/src/httpserver.cpp
    1+++ b/src/httpserver.cpp
    2@@ -263,6 +263,7 @@ std::string RequestMethodString(HTTPRequest::RequestMethod m)
    3 /** HTTP request callback */
    4 static void http_request_cb(struct evhttp_request* req, void* arg)
    5 {
    6+    throw std::runtime_error{"Hello"};
    7     evhttp_connection* conn{evhttp_request_get_connection(req)};
    8     // Track active requests
    9     {
    

    and running a functional test such as test/functional/feature_abortnode.py.

    http.client.RemoteDisconnected not specifying errno to ConnectionResetError-ctor: https://github.com/python/cpython/blob/ce4b0ede16aea62ee7b1e02df7e1538102a356da/Lib/http/client.py#L1556C9-L1556C29

    Log before

     02025-11-14T20:53:05.272804Z TestFramework (ERROR): Unexpected exception
     1Traceback (most recent call last):
     2  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 138, in main
     3    self.setup()
     4    ~~~~~~~~~~^^
     5  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 268, in setup
     6    self.setup_network()
     7    ~~~~~~~~~~~~~~~~~~^^
     8  File "/home/hodlinator/bc/3/./build/test/functional/feature_abortnode.py", line 21, in setup_network
     9    self.setup_nodes()
    10    ~~~~~~~~~~~~~~~~^^
    11  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 381, in setup_nodes
    12    self.start_nodes()
    13    ~~~~~~~~~~~~~~~~^^
    14  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 527, in start_nodes
    15    node.wait_for_rpc_connection()
    16    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
    17  File "/home/hodlinator/bc/3/test/functional/test_framework/test_node.py", line 326, in wait_for_rpc_connection
    18    rpc.getblockcount()
    19    ~~~~~~~~~~~~~~~~~^^
    20  File "/home/hodlinator/bc/3/test/functional/test_framework/coverage.py", line 50, in __call__
    21    return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
    22  File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 137, in __call__
    23    response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
    24                       ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    25  File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 111, in _request
    26    return self._get_response()
    27           ~~~~~~~~~~~~~~~~~~^^
    28  File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 174, in _get_response
    29    http_response = self.__conn.getresponse()
    30  File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 1430, in getresponse
    31    response.begin()
    32    ~~~~~~~~~~~~~~^^
    33  File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 331, in begin
    34    version, status, reason = self._read_status()
    35                              ~~~~~~~~~~~~~~~~~^^
    36  File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 300, in _read_status
    37    raise RemoteDisconnected("Remote end closed connection without"
    38                             " response")
    39http.client.RemoteDisconnected: Remote end closed connection without response
    

    Log after

     02025-11-14T20:48:10.552126Z TestFramework (ERROR): Unexpected exception
     1Traceback (most recent call last):
     2  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 138, in main
     3    self.setup()
     4    ~~~~~~~~~~^^
     5  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 268, in setup
     6    self.setup_network()
     7    ~~~~~~~~~~~~~~~~~~^^
     8  File "/home/hodlinator/bc/3/./build/test/functional/feature_abortnode.py", line 21, in setup_network
     9    self.setup_nodes()
    10    ~~~~~~~~~~~~~~~~^^
    11  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 381, in setup_nodes
    12    self.start_nodes()
    13    ~~~~~~~~~~~~~~~~^^
    14  File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 527, in start_nodes
    15    node.wait_for_rpc_connection()
    16    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
    17  File "/home/hodlinator/bc/3/test/functional/test_framework/test_node.py", line 316, in wait_for_rpc_connection
    18    raise FailedToStartError(self._node_msg(
    19        f'bitcoind exited with status {self.process.returncode} during initialization. {str_error}'))
    20test_framework.test_node.FailedToStartError: [node 0] bitcoind exited with status -6 during initialization. terminate called after throwing an instance of 'std::runtime_error'
    21  what():  Hello
    22************************
    

    Note how even the C++ exception message is now included.

  2. qa: Account for errno not always being set for ConnectionResetError
    Logging issue can be triggered by:
    
    ```diff
    --- a/src/httpserver.cpp
    +++ b/src/httpserver.cpp
    @@ -263,6 +263,7 @@ std::string RequestMethodString(HTTPRequest::RequestMethod m)
     /** HTTP request callback */
     static void http_request_cb(struct evhttp_request* req, void* arg)
     {
    +    throw std::runtime_error{"Hello"};
         evhttp_connection* conn{evhttp_request_get_connection(req)};
         // Track active requests
         {
    ```
    
    http.client.RemoteDisconnected not specifying errno to ConnectionResetError-ctor:
    https://github.com/python/cpython/blob/ce4b0ede16aea62ee7b1e02df7e1538102a356da/Lib/http/client.py#L1556C9-L1556C29
    76e0e6087d
  3. DrahtBot added the label Tests on Nov 14, 2025
  4. DrahtBot commented at 9:10 pm on November 14, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33875.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK furszy, l0rinc, maflcko

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • Work around issue where socket timeouts don’t have errno set. -> Work around an issue where socket timeouts don’t have errno set. [missing article “an” makes the sentence slightly ungrammatical]

    drahtbot_id_5_m

  5. in test/functional/test_framework/test_node.py:374 in 76e0e6087d
    373+                    if isinstance(e, TimeoutError):
    374+                        error_num = errno.ETIMEDOUT
    375+                    # http.client.RemoteDisconnected inherits from this type and
    376+                    # doesn't specify errno.
    377+                    elif isinstance(e, ConnectionResetError):
    378+                        error_num = errno.ECONNRESET
    


    furszy commented at 8:43 pm on November 15, 2025:

    nit: might want to update the line below to state this could also happen due to an uncaught exception at the server side. Talking about this:

    0errno.ECONNRESET, # This might happen when the RPC server is in warmup
    

    hodlinator commented at 1:10 pm on November 17, 2025:

    Will try to come up with something in case I re-touch. (Edit: ->) Something like:

    0errno.ECONNRESET,  # This might happen when the RPC server is in warmup, or throws an exception and disconnects us
    
  6. furszy commented at 8:55 pm on November 15, 2025: member

    Tested ACK 76e0e6087d0310ec31f43d751de60adf0c0a2faa

    Thanks for improving this. It makes understanding internal issues simpler.

    It’d be nice if the upcoming http server implementation caught these unhandled exceptions, writes to std::cerr and returns a proper error instead of exposing the internal one via the http response. Tagging @pinheadmz.

  7. l0rinc approved
  8. l0rinc commented at 6:16 pm on November 19, 2025: contributor

    untested code review ACK 76e0e6087d0310ec31f43d751de60adf0c0a2faa

    This is a continuation of https://github.com/bitcoin/bitcoin/pull/30660/files#diff-7f22a082e3a80ca2f212e36193f87dd80237035afedb7f15b116ef7fa265f3eeR326, separating the existing TimeoutError to add extra details for ConnectionResetError as well.

  9. fanquake requested review from maflcko on Dec 17, 2025
  10. maflcko commented at 7:23 am on December 18, 2025: member

    review ACK 76e0e6087d0310ec31f43d751de60adf0c0a2faa 🌬

    Signature:

    0untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
    1RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
    2trusted comment: review ACK 76e0e6087d0310ec31f43d751de60adf0c0a2faa 🌬
    3spTSe0wbIGXTZ5gaWnx4bU4l3dlpjvpFHeUM/p2LYydK5Clcn/ZJqOeiwWb882xohyQcbYU9N0ex93ET33+PBA==
    
  11. maflcko commented at 7:23 am on December 18, 2025: member

    tested via:

     0diff --git a/src/httpserver.cpp b/src/httpserver.cpp
     1index 6cf47eba73..a43436ef9c 100644
     2--- a/src/httpserver.cpp
     3+++ b/src/httpserver.cpp
     4@@ -263,6 +263,7 @@ std::string RequestMethodString(HTTPRequest::RequestMethod m)
     5 /** HTTP request callback */
     6 static void http_request_cb(struct evhttp_request* req, void* arg)
     7 {
     8+    assert(false);
     9     evhttp_connection* conn{evhttp_request_get_connection(req)};
    10     // Track active requests
    11     {
    
  12. fanquake merged this on Dec 18, 2025
  13. fanquake closed this on Dec 18, 2025


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-12-23 03:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me