From 25bb3e67f3918bf03a5317da3138204886337347 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Wed, 3 Jun 2026 18:59:27 -0400 Subject: [PATCH 1/2] proxy-client: fix TSan data race in clientDestroy clientDestroy() reads m_context.connection to decide whether to use MP_LOG vs KJ_LOG, but Connection::~Connection() can set it to null concurrently from the event loop thread (via the disconnect_cb sync cleanup callback) while the destructor runs on an async cleanup thread, causing a TSan-reported data race. The race is exposed by the test added in commit 90be835 ("test: regression for ~ProxyClient destroy after peer disconnect"). The KJ_LOG fallback was only needed before commit 315ff53 ("refactor: Add ProxyContext EventLoop* member"), when logging required going through connection->m_loop. Since that commit, m_context.loop is a direct EventLoopRef that is always valid regardless of whether m_context.connection is null. The KJ_LOG branch is now dead code, so drop it and the connection check entirely. Co-Authored-By: Claude Sonnet 4.6 --- include/mp/proxy-types.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/mp/proxy-types.h b/include/mp/proxy-types.h index 70b05381..2e1460a9 100644 --- a/include/mp/proxy-types.h +++ b/include/mp/proxy-types.h @@ -644,11 +644,7 @@ struct CapRequestTraits<::capnp::Request<_Params, _Results>> template void clientDestroy(Client& client) { - if (client.m_context.connection) { - MP_LOG(*client.m_context.loop, Log::Debug) << "IPC client destroy " << CxxTypeName(client); - } else { - KJ_LOG(INFO, "IPC interrupted client destroy", CxxTypeName(client)); - } + MP_LOG(*client.m_context.loop, Log::Debug) << "IPC client destroy " << CxxTypeName(client); } template From 039e5ac14bd8bb8a0532431474fbfd70bf0a2557 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Wed, 3 Jun 2026 21:25:02 -0400 Subject: [PATCH 2/2] mpgen: iwyu changes required by previous commit gen.cpp uses IWYU pragma: keep for include which appears to be necessary for newer versions of capnproto (1.4.0 but not 1.1.0) --- src/mp/gen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mp/gen.cpp b/src/mp/gen.cpp index 29fd8a9e..4232dc84 100644 --- a/src/mp/gen.cpp +++ b/src/mp/gen.cpp @@ -6,6 +6,7 @@ #include #include +#include // IWYU pragma: keep #include #include #include @@ -329,12 +330,15 @@ static void Generate(kj::StringPtr src_prefix, cpp_client << "#include <" << include_path << ".h>\n"; cpp_client << "#include <" << include_path << ".proxy.h>\n"; cpp_client << "#include <" << include_path << ".proxy-types.h>\n"; + cpp_client << "#include \n"; cpp_client << "#include \n"; cpp_client << "#include \n"; - cpp_client << "#include \n"; + cpp_client << "#include \n"; cpp_client << "#include \n"; + cpp_client << "#include \n"; cpp_client << "#include \n"; cpp_client << "#include \n"; + cpp_client << "#include \n"; cpp_client << "#include <" << PROXY_TYPES << ">\n"; cpp_client << "// IWYU pragma: end_keep\n\n"; cpp_client << "namespace mp {\n"; @@ -346,8 +350,6 @@ static void Generate(kj::StringPtr src_prefix, cpp_types << "#include <" << include_path << ".h> // IWYU pragma: keep\n"; cpp_types << "#include <" << include_path << ".proxy.h>\n"; cpp_types << "#include <" << include_path << ".proxy-types.h> // IWYU pragma: keep\n"; - cpp_types << "#include \n"; - cpp_types << "#include \n"; cpp_types << "#include <" << PROXY_TYPES << ">\n\n"; cpp_types << "namespace mp {\n";