Skip to content

Commit 43dfe34

Browse files
committed
proxy: Call shutdownWrite() in Connection destructor
Flush pending Cap'n Proto release messages before closing the stream. When one side of a socket pair closes, the other side does not receive an onDisconnect event, so it relies on receiving release messages from the closing side to free its ProxyServer objects and shut down cleanly. Without this, Server objects are not freed by Cap'n Proto on disconnection.
1 parent aff37a9 commit 43dfe34

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

src/mp/proxy.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,28 @@ Connection::~Connection()
9999
// after the calls finish.
100100
m_rpc_system.reset();
101101

102+
// shutdownWrite is needed on Windows so pending data in the m_stream socket
103+
// will be sent instead of discarded when m_stream is destroyed. On unix,
104+
// this doesn't seem to be needed because data is sent more reliably.
105+
//
106+
// Sending pending data is important if the connection is a socketpair
107+
// because when one side of the socketpair is closed, the other side doesn't
108+
// seem to receive any onDisconnect event. So it is important for the other
109+
// side to instead receive Cap'n Proto "release" messages (see `struct
110+
// Release` in capnp/rpc.capnp) from local Client objects being destroyed so
111+
// the remote side can free resources and shut down cleanly. Without this,
112+
// when one side of a socket pair is closed the other side may not receive
113+
// these messages, preventing the remote side from freeing ProxyServer
114+
// resources and shutting down cleanly.
115+
try {
116+
m_stream->shutdownWrite();
117+
} catch (const kj::Exception& e) {
118+
// Ignore ENOTCONN: on macOS/FreeBSD (unlike Linux), shutdown(SHUT_WR)
119+
// returns ENOTCONN if the peer already closed the connection. This is
120+
// expected when the destructor is triggered by a remote disconnect.
121+
if (e.getType() != kj::Exception::Type::DISCONNECTED) throw;
122+
}
123+
102124
// ProxyClient cleanup handlers are in sync list, and ProxyServer cleanup
103125
// handlers are in the async list.
104126
//

0 commit comments

Comments
 (0)