diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-22 05:49:04 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-22 05:49:04 +0800 |
| commit | 4616e6fc4230a74b0ded4d56c8a6b3b8402e09fb (patch) | |
| tree | 97f802d732ac454ad1702a2c89edc8b7555a8882 /binding/unreal | |
| parent | 9c0ec40e816eb8f74dda6ba14140ec3de1100c26 (diff) | |
fix(dmvopbridge): fix unsafe socket cleanup and thread lifecycle
Diffstat (limited to 'binding/unreal')
| -rw-r--r-- | binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.cpp | 33 | ||||
| -rw-r--r-- | binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.h | 2 |
2 files changed, 21 insertions, 14 deletions
diff --git a/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.cpp b/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.cpp index 211b4ba..15a11e0 100644 --- a/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.cpp +++ b/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.cpp @@ -4,10 +4,22 @@ UDMVOPClient::UDMVOPClient() : Socket(nullptr) {} -UDMVOPClient::~UDMVOPClient() { +UDMVOPClient::~UDMVOPClient() { cleanup(); } + +void UDMVOPClient::cleanup() { + // SAFETY: signal the reader thread to stop, then close the socket so + // Recv() unblocks immediately. After the thread exits, destroy the socket. + // The thread checks bRunning on every iteration and after each Recv(). bRunning.store(false); - // Don't call Disconnect() here — UE GC may crash. - // Socket will be cleaned up by the OS on process exit. + if (Socket) { + Socket->Close(); // unblocks Recv() in the reader thread + } + if (ReaderThread.joinable()) + ReaderThread.join(); // thread exits after Recv() fails + bRunning check + if (Socket) { + ISocketSubsystem::Get()->DestroySocket(Socket); + Socket = nullptr; + } } void UDMVOPClient::Connect(const FString &Host, int32 Port) { @@ -26,6 +38,7 @@ void UDMVOPClient::Connect(const FString &Host, int32 Port) { Addr->SetPort(Port); Socket = FTcpSocketBuilder(TEXT("DMVOPSocket")).AsNonBlocking().Build(); + if (!Socket->Connect(*Addr)) { UE_LOG(LogTemp, Error, TEXT("DMVOP: Failed to connect")); Socket->Close(); @@ -41,12 +54,12 @@ void UDMVOPClient::Connect(const FString &Host, int32 Port) { TWeakObjectPtr<UDMVOPClient> WeakThis(this); FSocket *Sock = Socket; - ReaderThread = std::thread([WeakThis, Sock]() { + ReaderThread = std::thread([WeakThis, Sock, this]() { TArray<uint8> Buf; Buf.SetNumUninitialized(4096); FString Partial; - while (true) { + while (this->bRunning.load()) { int32 Read = 0; if (!Sock->Recv(Buf.GetData(), Buf.Num(), Read, ESocketReceiveFlags::None) || @@ -80,14 +93,6 @@ void UDMVOPClient::Connect(const FString &Host, int32 Port) { } } }); - - ReaderThread.detach(); } -void UDMVOPClient::Disconnect() { - bRunning.store(false); - if (Socket) { - Socket->Close(); - Socket = nullptr; - } -} +void UDMVOPClient::Disconnect() { cleanup(); } diff --git a/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.h b/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.h index b05f8ce..b82c2dc 100644 --- a/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.h +++ b/binding/unreal/DMVOPBridge/Source/DMVOPBridge/DMVOPBridgeClient.h @@ -32,6 +32,8 @@ public: FOnDMVOPVoiceInput OnVoiceInput; private: + void cleanup(); + FSocket *Socket; FString PartialLine; std::thread ReaderThread; |
