diff --git a/lldb/include/lldb/Host/JSONTransport.h b/lldb/include/lldb/Host/JSONTransport.h index 6b114ee497a8b..c3a90cb0c3364 100644 --- a/lldb/include/lldb/Host/JSONTransport.h +++ b/lldb/include/lldb/Host/JSONTransport.h @@ -259,9 +259,11 @@ template class IOTransport : public JSONTransport { if (!m_buffer.empty()) handler.OnError(llvm::make_error( std::string(m_buffer.str()))); + // Move the read handle to a local before notifying the handler. The + // handler may destroy this transport (e.g. by erasing it from a + // connection map), so accessing members after OnClosed() is unsafe. + auto read_handle = std::move(m_read_handle); handler.OnClosed(); - // On EOF, remove the read handle from the MainLoop. - m_read_handle.reset(); } } diff --git a/lldb/unittests/Host/JSONTransportTest.cpp b/lldb/unittests/Host/JSONTransportTest.cpp index 2c26f94213773..3e977a70f5d4e 100644 --- a/lldb/unittests/Host/JSONTransportTest.cpp +++ b/lldb/unittests/Host/JSONTransportTest.cpp @@ -479,6 +479,15 @@ TEST_F(HTTPDelimitedJSONTransportTest, ReadWithEOF) { ASSERT_THAT_ERROR(Run(), Succeeded()); } +TEST_F(HTTPDelimitedJSONTransportTest, ReadWithEOFDestroyTransportOnClose) { + input.CloseWriteFileDescriptor(); + EXPECT_CALL(message_handler, OnClosed()).WillOnce([this]() { + transport.reset(); + loop.RequestTermination(); + }); + ASSERT_THAT_ERROR(loop.Run().takeError(), Succeeded()); +} + TEST_F(HTTPDelimitedJSONTransportTest, ReaderWithUnhandledData) { std::string json = R"json({"str": "foo"})json"; std::string message = @@ -588,6 +597,15 @@ TEST_F(JSONRPCTransportTest, ReadWithEOF) { ASSERT_THAT_ERROR(Run(), Succeeded()); } +TEST_F(JSONRPCTransportTest, ReadWithEOFDestroyTransportOnClose) { + input.CloseWriteFileDescriptor(); + EXPECT_CALL(message_handler, OnClosed()).WillOnce([this]() { + transport.reset(); + loop.RequestTermination(); + }); + ASSERT_THAT_ERROR(loop.Run().takeError(), Succeeded()); +} + TEST_F(JSONRPCTransportTest, ReaderWithUnhandledData) { std::string message = R"json({"req": "foo")json"; // Write an incomplete message and close the handle.