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:

    --- 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
         {
    

    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

    <details><summary>Before/after log examples</summary>

    Log before

    2025-11-14T20:53:05.272804Z TestFramework (ERROR): Unexpected exception
    Traceback (most recent call last):
      File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 138, in main
        self.setup()
        ~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 268, in setup
        self.setup_network()
        ~~~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/./build/test/functional/feature_abortnode.py", line 21, in setup_network
        self.setup_nodes()
        ~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 381, in setup_nodes
        self.start_nodes()
        ~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/test_framework.py", line 527, in start_nodes
        node.wait_for_rpc_connection()
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/test_node.py", line 326, in wait_for_rpc_connection
        rpc.getblockcount()
        ~~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/coverage.py", line 50, in __call__
        return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
      File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 137, in __call__
        response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
                           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 111, in _request
        return self._get_response()
               ~~~~~~~~~~~~~~~~~~^^
      File "/home/hodlinator/bc/3/test/functional/test_framework/authproxy.py", line 174, in _get_response
        http_response = self.__conn.getresponse()
      File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 1430, in getresponse
        response.begin()
        ~~~~~~~~~~~~~~^^
      File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 331, in begin
        version, status, reason = self._read_status()
                                  ~~~~~~~~~~~~~~~~~^^
      File "/nix/store/62fdlzq1x1ak2lsxp4ij7ip5k9nia3hc-python3-3.13.7/lib/python3.13/http/client.py", line 300, in _read_status
        raise RemoteDisconnected("Remote end closed connection without"
                                 " response")
    http.client.RemoteDisconnected: Remote end closed connection without response
    

    Log after

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

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

    </details>

  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

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

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

    <!--021abf342d371248e50ceaed478a90ca-->

    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 <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    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]

    <sup>drahtbot_id_5_m</sup>

  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:

    errno.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:

    errno.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 🌬

    <details><summary>Show signature</summary>

    Signature:

    untrusted 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}"
    RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
    trusted comment: review ACK 76e0e6087d0310ec31f43d751de60adf0c0a2faa 🌬
    spTSe0wbIGXTZ5gaWnx4bU4l3dlpjvpFHeUM/p2LYydK5Clcn/ZJqOeiwWb882xohyQcbYU9N0ex93ET33+PBA==
    

    </details>

  11. maflcko commented at 7:23 AM on December 18, 2025: member

    tested via:

    diff --git a/src/httpserver.cpp b/src/httpserver.cpp
    index 6cf47eba73..a43436ef9c 100644
    --- 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)
     {
    +    assert(false);
         evhttp_connection* conn{evhttp_request_get_connection(req)};
         // Track active requests
         {
    
  12. fanquake merged this on Dec 18, 2025
  13. fanquake closed this on Dec 18, 2025

  14. sedited referenced this in commit f8db928648 on Dec 27, 2025
  15. joshdoman referenced this in commit 57661ceac9 on Dec 27, 2025
  16. stickies-v referenced this in commit 9fa736f8e4 on Jan 22, 2026
  17. stringintech referenced this in commit f651a10526 on Feb 1, 2026
  18. hodlinator deleted the branch on Apr 9, 2026


maflcko

Labels

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: 2026-04-19 03:12 UTC

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