Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8013801
This is a documentation-only change meant to make upcoming commits ea…
ryanofsky Sep 3, 2026
e9bbe34
Correct the ThreadContext "Synchronization note", which said
ryanofsky Sep 10, 2026
33bd6f8
proxy-io: fix listener stuck at capacity after a local disconnect
ryanofsky Sep 3, 2026
7cbade8
proxy-io: fix race deleting a disconnected Connection twice
ryanofsky Sep 3, 2026
3a4a5eb
Fix a race between a thread exiting after making IPC calls and its
ryanofsky Sep 11, 2026
d746bb3
proxy-io: add Connection::disconnect() separating teardown from destr…
ryanofsky Jul 31, 2026
98d28df
proxy-io: add Connection::waitDrained() to wait for in-flight server …
ryanofsky Jul 31, 2026
40cfb93
test: cover draining in-flight server call after disconnect
ryanofsky Jul 31, 2026
936d487
Merge branch 'pr/keepconn' into pr/notrack
ryanofsky Sep 11, 2026
37e19f8
proxy-io: add EventLoop::incomingConnections()
ryanofsky Sep 11, 2026
57c7e30
proxy-io: let ServeStream take ownership of init object
ryanofsky Sep 11, 2026
42e246b
proxy-io: add destroy_connection parameter to ServeStream and Connect…
ryanofsky Sep 11, 2026
fb9b742
test: simplify TestSetup using ServeStream/ConnectStream
ryanofsky Sep 11, 2026
fc585ab
Merge branch 'pr/connserve' into pr/notrack
ryanofsky Sep 11, 2026
c092c18
proxy-io: manage Connection lifetime with shared_ptr
ryanofsky Sep 11, 2026
7635c12
proxy-io: keep client capability handles across disconnect
ryanofsky Jul 31, 2026
162b7a6
doc: scope Connection cleanup callbacks to per-thread map entries
ryanofsky Jul 31, 2026
f0a629d
proxy-io: make server object tracker a plain Connection member
ryanofsky Jul 31, 2026
6c7f1bf
ci: Check out bitcoin/bitcoin PR #35932 instead of master
ryanofsky Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/bitcoin-core-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ concurrency:

env:
BITCOIN_REPO: bitcoin/bitcoin
BITCOIN_CORE_REF: refs/heads/master
# Temporary: use PR #35932 until it merges; revert to refs/heads/master after
BITCOIN_CORE_REF: refs/pull/35932/merge
LLVM_VERSION: 22
LIBCXX_DIR: /tmp/libcxx-build/

Expand Down
1 change: 0 additions & 1 deletion example/calculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <fstream>
#include <functional>
#include <iostream>
#include <kj/async.h>
#include <kj/common.h>
#include <kj/memory.h>
#include <memory>
Expand Down
1 change: 0 additions & 1 deletion example/printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <cstring> // IWYU pragma: keep
#include <fstream>
#include <iostream>
#include <kj/async.h>
#include <kj/common.h>
#include <kj/memory.h>
#include <memory>
Expand Down
543 changes: 414 additions & 129 deletions include/mp/proxy-io.h

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions include/mp/proxy-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ auto PassField(Priority<1>, TypeList<LocalType&>, ServerContext& server_context,
const auto& params = server_context.call_context.getParams();
const auto& input = Make<StructField, Accessor>(params);
using Interface = typename Decay<decltype(input.get())>::Calls;
auto param = std::make_unique<ProxyClient<Interface>>(input.get(), server_context.proxy_server.m_context.connection, false);
auto param = std::make_unique<ProxyClient<Interface>>(input.get(), server_context.proxy_server.m_context.connection.get(), false);
fn.invoke(server_context, std::forward<Args>(args)..., *param);
}

Expand Down Expand Up @@ -734,7 +734,12 @@ void clientInvoke(ProxyClient& proxy_client, const GetRequest& get_request, Fiel
bool done = false;
const char* disconnected = nullptr;
proxy_client.m_context.loop->sync([&]() {
if (!proxy_client.m_context.connection) {
// Fail immediately on a disconnected connection instead of trying to
// send a request through it. (The connection object itself is always
// valid, since m_context holds shared ownership of it.) disconnected()
// is only meaningful on the event loop thread, which this sync()
// callback runs on.
if (proxy_client.m_context.connection->disconnected()) {
const Lock lock(thread_context.waiter->m_mutex);
done = true;
disconnected = "IPC client method called after disconnect.";
Expand Down
6 changes: 5 additions & 1 deletion include/mp/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ class EventLoopRef
//! Context data associated with proxy client and server classes.
struct ProxyContext
{
Connection* connection;
//! Connection this proxy object is associated with. Holding shared
//! ownership (Connection objects are always owned by shared_ptr, see
//! Connection::make) guarantees the Connection outlives this proxy
//! object, so the pointer stays valid even after a disconnect.
std::shared_ptr<Connection> connection;
EventLoopRef loop;
CleanupList cleanup_fns;

Expand Down
14 changes: 7 additions & 7 deletions include/mp/type-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn&
// cancel_monitor.m_canceled was checked above and this
// code is running on the event loop thread.
std::tie(request_thread, inserted) = SetThread(
GuardedRef{thread_context.waiter->m_mutex, request_threads}, server.m_context.connection,
GuardedRef{thread_context.waiter->m_mutex, request_threads}, server.m_context.connection.get(),
[&] { return Accessor::get(call_context.getParams()).getCallbackThread(); });
// Initialize the request's results struct here on the event loop
// thread, so later getResults() calls on the execution thread
Expand Down Expand Up @@ -179,14 +179,14 @@ auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn&
if (erase_thread) {
// Look up the thread again without using existing
// iterator since entry may no longer be there after
// a disconnect. Destroy node after releasing
// Waiter::m_mutex, so the ProxyClient<Thread>
// destructor is able to use EventLoop::mutex
// without violating lock order.
// a disconnect. Destroy the node after releasing
// Waiter::m_mutex, so ~ProxyClient<Thread> does not
// run with the mutex held (see the SetThread
// disconnect callback).
ConnThreads::node_type removed;
{
Lock lock(thread_context.waiter->m_mutex);
removed = request_threads.extract(server.m_context.connection);
removed = request_threads.extract(server.m_context.connection.get());
}
}
});
Expand Down Expand Up @@ -215,7 +215,7 @@ auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn&
if (!context_arg.hasThread()) {
// No client thread specified — dispatch through the server thread
// pool, picking the slot with the smallest in-flight depth.
auto* connection = server.m_context.connection;
auto* connection = server.m_context.connection.get();
auto& pool = connection->m_thread_pool;
if (pool.empty()) {
MP_LOG(loop, Log::Error)
Expand Down
Loading