Fix error handling when creating clients (mp::ConnectStream) - #298
Fix error handling when creating clients (mp::ConnectStream)#298xyzconstant wants to merge 4 commits into
mp::ConnectStream)#298Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline and AI policy for information on the review process. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
ConnectStream
|
Thanks for following up to #183 with these tests. They do seem potentially useful. Here is feedback I'd have:
Overall the tests here seem reasonable to add. It seems good to have at least 1-2 tests verifying disconnects are processed when a capnproto client connects to a non-capnproto server. (Relatedly, there are also other disconnect tests that could be added at different points during capnproto connections, which I started to write in #201 (comment) and https://github.com/ryanofsky/libmultiprocess/commits/pr/distest.2 but was never able to really finish due to complexity of trying to set up and cover all of the relevant cases. Just mentioning this for completeness, though. There's probably not an obviously place to follow up with this at the moment.) |
d3390db to
cdada78
Compare
cdada78 to
4f05dbe
Compare
595e258 to
bc85c9a
Compare
ConnectStreamConnectStream
02b300c to
7c24708
Compare
|
Thanks for the feedback @ryanofsky! I've just rebased to master now that #269 has been merged and added a new commit to move Also, I've made changes to the tests (please check the description), keeping the first 2 tests (Notice that I've dropped the
This is my current focus. I'm looking more into it, but I think this work might need its own branch so we keep test coverage scoped to this PR.
Good, these ideas are great and definitely worth exploring. Happy to tackle them after this. |
|
This PR is now ready for review. I've updated the description as well! |
02f2822 to
bd3c83d
Compare
ConnectStreammp::ConnectStream)
9b93947 to
82f7ef2
Compare
|
re: #298 (comment) Thanks for the review @ryanofsky! Addressed your feedback and force-pushed, I hope the commit history is cleaner now. Opened issues (#308 and #309) and updated the PR title and description as well. Also, please note that I've added 2 new tests (I just noticed I pushed them right after your latest review, so you might have missed them), and I think they're valuable for showcasing the difference with an Init interface without |
82f7ef2 to
9078674
Compare
9078674 to
a2e0007
Compare
e4530f8 to
f3355b5
Compare
|
Rebased on master which now includes #274. Adapted the tests to the stream API ( |
ryanofsky
left a comment
There was a problem hiding this comment.
Code review f3355b5. I need to take more time to understand the tests but the bugfix looks right and useful for improving the stability of the C++ IPC client if it connects to a server that disconnects right away.
I left a minor suggestion below. Also would note that this conflicts with #231 and while I think conflicts mostly just come from moved code, it could be useful to try merging the two PRs and making sure the new tests do not introduce any unix-isms.
| passDataPointers @22 (arg :List(Data)) -> (result :List(Data)); | ||
| } | ||
|
|
||
| interface FooInit $Proxy.wrap("mp::test::FooInit") { |
There was a problem hiding this comment.
In commit "Add test coverage for ConnectStream" (31c1ac2)
Am curious why this new FooInit interface is needed and existing Foo interface isn't used.
It also seems like a potentially complicating factor that could make the tests harder to debug & understand for this to have a construct method. I wonder if it could be dropped or at least the Thread map parameters could be dropped since it doesn't look like anything in these tests requires threadmaps
EDIT: Oh, I see in next commit it looks like there are new tests that rely on the construct call failing. I think it would be to only use the FooInit type for the tests which actually need the construct method, and use FooInterface for other tests. Also would be good to drop ThreadMap parameters as I believe they should not be needed.
There was a problem hiding this comment.
Nice suggestion!
Addressed it at 65eab9d by removing the ThreadMap parameters.
There was a problem hiding this comment.
Regarding the FooInit/FooInterface split, the tests already follow this. Only the 4 tests that require the construct() call use FooInit.
Also, I've replaced the initThreadMap call with a simple add(1, 2) in the "ConnectStream defers disconnect failure to the first IPC request for interfaces without construct()" test case.
…ctions` 496fb84 test: cover immediate client disconnects for `ListenConnections` (xyzconstant) 140d9ba test: allow custom log handler in `ListenSetup` (xyzconstant) Pull request description: Following on testing the reversed direction *ryanofsky* [suggested](#298 (comment)) in #298, this PR adds a test to cover immediate client disconnects on the server side. Additionally, this test adds `DefaultLogHandler` and a `log_handler` parameter to `ListenSetup`, allowing individual tests to observe logs by passing a custom log handler. The new test takes advantage of this by catching and skipping `Uncaught exception in daemonized task.` logs. NOTE: an issue surfaced on the macOS job, the `accept()` call in `ListenConnections` [fails](https://github.com/bitcoin-core/libmultiprocess/actions/runs/29545518652/job/87776862017?pr=310) for the closed connection, this is a Cap'n Proto bug as reported by *ViniciusCestarii* in #310 (review) and its fix is [available](capnproto/capnproto@7df5bd0#diff-ec577ad66535f58f6d7396ea51d3e56c0065308aa8fb02751cd6a8cfaa67252fR1358-R1372) in the v2 branch. ACKs for top commit: ryanofsky: Code review ACK 496fb84. Since last review just tightened the checks to only allow the error on macos Tree-SHA512: 6347b433d03968541be58b893746f707ce905d0fe35ddfaa858439d73cc0850a9d5077a472ff6bad91c8de67fb3ef43e2b303dcf73c6e9d6ef555fce40327f96
c435ef7 to
8fb3b5b
Compare
A later commit will consume the `UnixListener` class in another test file, so move it to a shared one.
This commit introduces a new test file `connect_tests.cpp` for testing the `ConnectStream` function. It also adds a `FooInit` test interface declaring a `construct()` method, which `ConnectStream` calls implicitly when present.
Two bugs that have always been present: 1. `ConnectStream` registered the `onDisconnect` handler that deletes the `Connection` before the `ProxyClient` object owning it was created, so an early disconnect could delete the `Connection` while the client constructor was reading it (bitcoin-core#308). 2. A `construct()` method failing during client construction caused a `Connection` leak. Normally, cleanup happens in the destructor but a constructor that throws leaves no object behind, so it never runs, resulting in an event loop ref preventing `EventLoop::loop()` from exiting (bitcoin-core#309). Fix the first by making `ProxyClientBase` responsible for the connection when `destroy_connection` is true, registering the delete-on-disconnect handler at the end of its constructor. Fix the second by running the cleanup functions before rethrowing. Fixes bitcoin-core#308 Fixes bitcoin-core#309
|
Rebased with master and fixed surfaced IWYU issues. Additionally, addressed @ryanofsky's feedback by removing the |
8fb3b5b to
bb47369
Compare
Avoid use-after-free if the socket is disconnected before
ConnectStreamconnects (#308), and avoid leaks and hangs if clientconstruct()calls throw (#309). Also add tests to cover these and other client connection errors, as suggested by @ryanofsky.The following cases are tested:
ConnectStreamthrows during theconstruct()call)construct()(the failure is deferred to the first IPC request)accept()) that disconnects after some data arrivesAdditionally, a new
FooInittest interface is added, and theUnixListenerclass introduced in #269 is extracted to a shared file so the newconnect_tests.cppfile can use it.Note: Clients that own their connection now delete it on unexpected disconnects, so calls after a server disconnect fail with "called after disconnect" instead of "interrupted by disconnect" (one test.cpp assertion updated accordingly).