http: Track active requests and wait for last to finish#19420
http: Track active requests and wait for last to finish#19420promag wants to merge 2 commits intobitcoin:masterfrom
Conversation
|
|
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
62f6c7c to
bc744d9
Compare
|
@laanwj ping, again 😅 |
|
There is an issue which is fixed in #19434 - complete callback isn't called if client closes the connection. |
|
Interesting! -- this PR brings the run time of |
There was a problem hiding this comment.
Concept ACK, the code looks fine, tests pass and feature_abortnode.py for instance runs much faster.
Also, you may want to see libevent/libevent#643 and libevent/libevent#591.
|
Concept ACK |
bc744d9 to
ea724b9
Compare
|
@laanwj don't you miss reviewing this code? 😅 |
Does this change require bumping the minimum enforced libevent version from 2.0.21 to 2.1? |
There was a problem hiding this comment.
Light approach ACK ea724b9 based on code review, looked at the libevent repo, doc/dependencies and configure.ac, rebased, debug build, ran unit tests, re-verified that test/functional/feature_abortnode.py runs far faster (under 2 seconds with debug build on a slow CPU), ran mainnet/signet/testnet nodes with http logging on and made a few CLI calls, checked nodes shutdown. Modulo we would need to bump the minimum required version of libevent from 2.0.21 to 2.1.
debug log on signet shutdown
2022-03-23T11:57:59Z [http] Received a POST request for / from 127.0.0.1:33432
2022-03-23T11:57:59Z [init] Interrupting HTTP server
2022-03-23T11:57:59Z [init] tor: Thread interrupt
2022-03-23T11:57:59Z [init] Shutdown: In progress...
2022-03-23T11:57:59Z [shutoff] Unregistering HTTP handler for / (exactmatch 1)
2022-03-23T11:57:59Z [shutoff] Unregistering HTTP handler for /wallet/ (exactmatch 0)
2022-03-23T11:57:59Z [shutoff] Stopping HTTP server
2022-03-23T11:57:59Z [shutoff] Waiting for HTTP worker threads to exit
2022-03-23T11:57:59Z [addcon] addcon thread exit
2022-03-23T11:57:59Z [torcontrol] RemoveLocal(xxx.onion:38333)
2022-03-23T11:57:59Z [torcontrol] torcontrol thread exit
2022-03-23T11:57:59Z [opencon] opencon thread exit
2022-03-23T11:57:59Z [http] Exited http event loop
2022-03-23T11:57:59Z [shutoff] Waiting for HTTP event thread to exit
2022-03-23T11:57:59Z [shutoff] Stopped HTTP server
2022-03-23T11:57:59Z [net] net thread exit
2022-03-23T11:57:59Z [msghand] msghand thread exit
2022-03-23T11:58:00Z [i2paccept] i2paccept thread exit
2022-03-23T11:58:00Z [shutoff] DumpAnchors: Flush 2 outbound block-relay-only peer addresses to anchors.dat started
2022-03-23T11:58:00Z [shutoff] DumpAnchors: Flush 2 outbound block-relay-only peer addresses to anchors.dat completed (0.01s)
2022-03-23T11:58:00Z [scheduler] scheduler thread exit
2022-03-23T11:58:00Z [shutoff] I2P: Destroying session 99c6a79e84
2022-03-23T11:58:00Z [shutoff] Writing 0 unbroadcast transactions to disk.
2022-03-23T11:58:00Z [shutoff] Dumped mempool: 7.4e-05s to copy, 0.008535s to dump
2022-03-23T11:58:00Z [shutoff] [default wallet] Releasing wallet
2022-03-23T11:58:00Z [shutoff] [blank] Releasing wallet
2022-03-23T11:58:00Z [shutoff] [encrypted blank descriptor] Releasing wallet
2022-03-23T11:58:00Z [shutoff] [disable private keys] Releasing wallet
2022-03-23T11:58:00Z [shutoff] [disable private keys and blank] Releasing wallet
2022-03-23T11:58:00Z [shutoff] [default settings] Releasing wallet
2022-03-23T11:58:00Z [shutoff] Shutdown: done
Commit message: "http: Relese server before waiting for event base loop exit" -> s/Relese/Release/
| static std::vector<evhttp_bound_socket *> boundSockets; | ||
| //! Track active requests | ||
| static Mutex g_requests_mutex; | ||
| static std::condition_variable g_requests_cv; |
There was a problem hiding this comment.
662cba4 maybe add these headers
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -21,8 +21,10 @@
#include <util/threadnames.h>
#include <util/translation.h>
+#include <condition_variable>
#include <deque>
#include <memory>
+#include <mutex>
#include <stdio.h>| } | ||
| } | ||
| if (eventHTTP) { | ||
| event_base_once(eventBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) { |
There was a problem hiding this comment.
ea724b9 curious why you added this line (maybe describe the change in the commit message)
The other place in this codebase that calls event_base_once() to schedule a one-time event is torcontrol.cpp in InterruptTorControl.
There was a problem hiding this comment.
This is a way to call evhttp_free in the event base thread, meaning it's not called concurrently with the handling of unfinished request connections.
Done in #24681. |
…to 2.1.8 e40779a refactor: Remove outdated libevent logging code (Fabian Jahr) 0598f36 refactor: account for requiring libevent 2.1.8+ (fanquake) aaf72d6 build: Bump libevent minimum version up to 2.1.8 (Hennadii Stepanov) Pull request description: Required to support new functionality in bitcoin/bitcoin#19420. `libevent` availability: https://repology.org/project/libevent/versions ACKs for top commit: laanwj: Code review ACK e40779a fanquake: ACK e40779a Tree-SHA512: ccb14ea2f591484a3df5bc4a19f4f5400ef6b1cfb7dc45dd99f96cb948748215ed3b5debc34869763c91b8c7a26993fdb9b870950c0743c4d01038ab27c5e4e2
|
Are you still working on this? |
|
Closing this as it has not had any activity in a while. If you are interested in continuing work on this, please leave a comment so that it can be reopened. |
… - 2nd attempt 60978c8 test: Reduce extended timeout on abortnode test (Fabian Jahr) 660bdbf http: Release server before waiting for event base loop exit (João Barbosa) 8c6d007 http: Track active requests and wait for last to finish (João Barbosa) Pull request description: This revives #19420. Since promag is not so active at the moment, I can support this to finally get it merged. The PR is rebased and comments by jonatack have been addressed. Once this is merged, I will also reopen #19434. ACKs for top commit: achow101: ACK 60978c8 stickies-v: re-ACK [60978c8](60978c8) hebasto: ACK 60978c8 Tree-SHA512: eef0fe1081e9331b95cfafc71d82f2398abd1d3439dac5b2fa5c6d9c0a3f63ef19adde1c38c88d3b4e7fb41ce7c097943f1815c10e33d165918ccbdec512fe1c
… finish - 2nd attempt 60978c8 test: Reduce extended timeout on abortnode test (Fabian Jahr) 660bdbf http: Release server before waiting for event base loop exit (João Barbosa) 8c6d007 http: Track active requests and wait for last to finish (João Barbosa) Pull request description: This revives bitcoin#19420. Since promag is not so active at the moment, I can support this to finally get it merged. The PR is rebased and comments by jonatack have been addressed. Once this is merged, I will also reopen bitcoin#19434. ACKs for top commit: achow101: ACK 60978c8 stickies-v: re-ACK [60978c8](bitcoin@60978c8) hebasto: ACK 60978c8 Tree-SHA512: eef0fe1081e9331b95cfafc71d82f2398abd1d3439dac5b2fa5c6d9c0a3f63ef19adde1c38c88d3b4e7fb41ce7c097943f1815c10e33d165918ccbdec512fe1c
…ase of remote client disconnection 68f23f5 http: bugfix: track closed connection (stickies-v) 084d037 http: log connection instead of request count (stickies-v) 41f9027 http: refactor: use encapsulated HTTPRequestTracker (stickies-v) Pull request description: #26742 significantly increased the http server shutdown speed, but also introduced a bug (#27722 - see bitcoin/bitcoin#27722 (comment) for steps to reproduce on master) that causes http server shutdown to halt in case of a remote client disconnection. This happens because `evhttp_request_set_on_complete_cb` is never called and thus the request is never removed from `g_requests`. This PR fixes that bug, and improves robustness of the code by encapsulating the request tracking logic. Earlier approaches (#27909, #27245, #19434) attempted to resolve this but [imo are fundamentally unsafe](bitcoin/bitcoin#27909 (comment)) because of differences in lifetime between an `evhttp_request` and `evhttp_connection`. We don't need to keep track of open requests or connections, we just [need to ensure](bitcoin/bitcoin#19420 (comment)) that there are no active requests on server shutdown. Because a connection can have multiple requests, and a request can be completed in various ways (the request actually being handled, or the client performing a remote disconnect), keeping a counter per connection seems like the approach with the least overhead to me. Fixes #27722 ACKs for top commit: vasild: ACK 68f23f5 theStack: ACK 68f23f5 Tree-SHA512: dfa711ff55ec75ba44d73e9e6fac16b0be25cf3c20868c2145a844a7878ad9fc6998d9ff62d72f3a210bfa411ef03d3757b73d68a7c22926e874c421e51444d6
…emote client disconnection 68f23f5 http: bugfix: track closed connection (stickies-v) 084d037 http: log connection instead of request count (stickies-v) 41f9027 http: refactor: use encapsulated HTTPRequestTracker (stickies-v) Pull request description: bitcoin#26742 significantly increased the http server shutdown speed, but also introduced a bug (bitcoin#27722 - see bitcoin#27722 (comment) for steps to reproduce on master) that causes http server shutdown to halt in case of a remote client disconnection. This happens because `evhttp_request_set_on_complete_cb` is never called and thus the request is never removed from `g_requests`. This PR fixes that bug, and improves robustness of the code by encapsulating the request tracking logic. Earlier approaches (bitcoin#27909, bitcoin#27245, bitcoin#19434) attempted to resolve this but [imo are fundamentally unsafe](bitcoin#27909 (comment)) because of differences in lifetime between an `evhttp_request` and `evhttp_connection`. We don't need to keep track of open requests or connections, we just [need to ensure](bitcoin#19420 (comment)) that there are no active requests on server shutdown. Because a connection can have multiple requests, and a request can be completed in various ways (the request actually being handled, or the client performing a remote disconnect), keeping a counter per connection seems like the approach with the least overhead to me. Fixes bitcoin#27722 ACKs for top commit: vasild: ACK 68f23f5 theStack: ACK 68f23f5 Tree-SHA512: dfa711ff55ec75ba44d73e9e6fac16b0be25cf3c20868c2145a844a7878ad9fc6998d9ff62d72f3a210bfa411ef03d3757b73d68a7c22926e874c421e51444d6
This PR calls
evhttp_freebefore releasing event base. But according toevhttp_freedocs:So this PR also tracks active requests with libevent and waits for last request to finish. This requires libevent 2.1 due to
evhttp_request_set_on_complete_cb(https://github.com/libevent/libevent/blob/master/whatsnew-2.1.txt).Finally, the call to
evhttp_freeis done in the event base loop to avoid concurrency issues.Now test/functional/feature_abortnode.py quits normally, not due to socket timeouts.