From b0baf6f205f98aaa301b7dca2ae77a416640e659 Mon Sep 17 00:00:00 2001 From: fanlumaster <1730976608@qq.com> Date: Tue, 13 May 2025 10:06:52 +0800 Subject: [PATCH] [IPC]: Use an aux namedpipe to clear main namedpipe left by last process --- server/src/ipc/event_listener.cpp | 60 ++++++++++++++++++++++++++++++- server/src/ipc/event_listener.h | 1 + server/src/ipc/ipc.cpp | 56 +++++++++++++++++++++++------ server/src/ipc/ipc.h | 5 +++ server/src/main.cpp | 9 +++++ 5 files changed, 120 insertions(+), 11 deletions(-) diff --git a/server/src/ipc/event_listener.cpp b/server/src/ipc/event_listener.cpp index ac00802a..c564738b 100644 --- a/server/src/ipc/event_listener.cpp +++ b/server/src/ipc/event_listener.cpp @@ -1,6 +1,8 @@ #include "event_listener.h" #include #include +#include +#include #include #include "Ipc.h" #include "boost/algorithm/string/case_conv.hpp" @@ -405,12 +407,14 @@ void EnqueueTask(TaskType type) void EventListenerLoopThread() { - int numEvents = FANY_IME_EVENT_ARRAY.size(); while (true) { spdlog::info("Pipe starts to wait"); + OutputDebugString(L"Pipe starts to wait"); BOOL connected = ConnectNamedPipe(hPipe, NULL); spdlog::info("Pipe connected: {}", connected); + OutputDebugString(fmt::format(L"Pipe connected: {}", connected).c_str()); + ::mainConnected = connected; if (connected) { while (true) @@ -427,6 +431,7 @@ void EventListenerLoopThread() if (!readResult || bytesRead == 0) // Disconnected or error { // TODO: Log + OutputDebugString(L"Pipe disconnected or error"); break; } @@ -455,6 +460,7 @@ void EventListenerLoopThread() { // TODO: } + OutputDebugString(L"Pipe disconnected"); DisconnectNamedPipe(hPipe); } @@ -462,4 +468,56 @@ void EventListenerLoopThread() pipe_queueCv.notify_one(); ::CloseNamedPipe(); } + +void AuxPipeEventListenerLoopThread() +{ + while (true) + { + spdlog::info("Aux Pipe starts to wait"); + OutputDebugString(L"Aux Pipe starts to wait"); + BOOL connected = ConnectNamedPipe(hAuxPipe, NULL); + spdlog::info("Aux Pipe connected: {}", connected); + OutputDebugString(fmt::format(L"Aux Pipe connected: {}", connected).c_str()); + if (connected) + { + wchar_t buffer[128] = {0}; + DWORD bytesRead = 0; + BOOL readResult = ReadFile( // + hAuxPipe, // + buffer, // + sizeof(buffer), // + &bytesRead, // + NULL // + ); + if (!readResult || bytesRead == 0) // Disconnected or error + { + // TODO: Log + } + else + { + std::wstring message(buffer, bytesRead / sizeof(wchar_t)); + OutputDebugString(message.c_str()); + + if (message == L"kill") + { + OutputDebugString(L"Aux Pipe to disconnect main pipe"); + if (::mainConnected) + { + OutputDebugString(L"Really disconnect main pipe"); + // DisconnectNamedPipe(hPipe); + CancelSynchronousIo(::mainPipeThread); + OutputDebugString(L"End disconnect main pipe"); + } + } + } + } + else + { + // TODO: + } + OutputDebugString(L"Aux Pipe disconnected"); + DisconnectNamedPipe(hAuxPipe); + } + ::CloseAuxNamedPipe(); +} } // namespace FanyNamedPipe \ No newline at end of file diff --git a/server/src/ipc/event_listener.h b/server/src/ipc/event_listener.h index 22b5b3e2..93ffed4d 100644 --- a/server/src/ipc/event_listener.h +++ b/server/src/ipc/event_listener.h @@ -22,4 +22,5 @@ namespace FanyNamedPipe { void WorkerThread(); void EventListenerLoopThread(); +void AuxPipeEventListenerLoopThread(); } // namespace FanyNamedPipe \ No newline at end of file diff --git a/server/src/ipc/ipc.cpp b/server/src/ipc/ipc.cpp index bc041ec3..83c147ca 100644 --- a/server/src/ipc/ipc.cpp +++ b/server/src/ipc/ipc.cpp @@ -1,4 +1,5 @@ #include "Ipc.h" +#include #include #include #include @@ -8,6 +9,7 @@ #include "ipc.h" #include "spdlog/spdlog.h" #include "utils/common_utils.h" +#include "fmt/xchar.h" #define LOW_INTEGRITY_SDDL_SACL \ SDDL_SACL \ @@ -164,16 +166,32 @@ int InitNamedPipe() // // Named Pipe // - hPipe = CreateNamedPipe(FANY_IME_NAMED_PIPE, // pipe name - PIPE_ACCESS_DUPLEX, // read/write access - PIPE_TYPE_MESSAGE // message type pipe - | PIPE_READMODE_MESSAGE // message-read mode - | PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max instances - BUFFER_SIZE, // output buffer size - BUFFER_SIZE, // input buffer size - 0, // client time-out - &sa // security attribute, for UWP/Metro apps + + // Nmaedpipe for IME communication + hPipe = CreateNamedPipe( // + FANY_IME_NAMED_PIPE, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + PIPE_TYPE_MESSAGE // message type pipe + | PIPE_READMODE_MESSAGE // message-read mode + | PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max instances + BUFFER_SIZE, // output buffer size + BUFFER_SIZE, // input buffer size + 0, // client time-out + &sa // security attribute, for UWP/Metro apps + ); + // Nmaedpipe for reconnecting main pipe + hAuxPipe = CreateNamedPipe( // + FANY_IME_AUX_NAMED_PIPE, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + PIPE_TYPE_MESSAGE // message type pipe + | PIPE_READMODE_MESSAGE // message-read mode + | PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max instances + 128, // output buffer size + 128, // input buffer size + 0, // client time-out + &sa // security attribute, for UWP/Metro apps ); if (hPipe == INVALID_HANDLE_VALUE) @@ -185,6 +203,15 @@ int InitNamedPipe() spdlog::info("Named pipe created successfully"); } + if (hAuxPipe == INVALID_HANDLE_VALUE) + { + OutputDebugString(fmt::format(L"CreateNamedPipe aux pipe failed: {}", GetLastError()).c_str()); + } + else + { + OutputDebugString(L"Named pipe aux pipe created successfully"); + } + return 0; } @@ -238,6 +265,15 @@ int CloseNamedPipe() return 0; } +int CloseAuxNamedPipe() +{ + if (hAuxPipe != INVALID_HANDLE_VALUE) + { + CloseHandle(hAuxPipe); + } + return 0; +} + int WriteDataToSharedMemory( // const std::wstring &candidate_string, // bool write_flag // diff --git a/server/src/ipc/ipc.h b/server/src/ipc/ipc.h index 88dc24f4..4e83d7de 100644 --- a/server/src/ipc/ipc.h +++ b/server/src/ipc/ipc.h @@ -9,7 +9,11 @@ inline const wchar_t *FANY_IME_SHARED_MEMORY = L"Local\\FanyImeSharedMemory"; inline const int BUFFER_SIZE = 4096; inline const wchar_t *FANY_IME_NAMED_PIPE = L"\\\\.\\pipe\\FanyImeNamedPipe"; +inline const wchar_t *FANY_IME_AUX_NAMED_PIPE = L"\\\\.\\pipe\\FanyImeAuxNamedPipe"; inline HANDLE hPipe = INVALID_HANDLE_VALUE; +inline HANDLE hAuxPipe = INVALID_HANDLE_VALUE; +inline bool mainConnected = false; +inline HANDLE mainPipeThread = NULL; // // Events from tsf to server @@ -67,6 +71,7 @@ int InitIpc(); int InitNamedPipe(); int CloseIpc(); int CloseNamedPipe(); +int CloseAuxNamedPipe(); int WriteDataToSharedMemory( // const std::wstring &candidate_string, // bool write_flag // diff --git a/server/src/main.cpp b/server/src/main.cpp index b06b0ed0..980a35e1 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -25,9 +25,16 @@ int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In std::thread worker(WorkerThread); std::thread listener(EventListenerLoopThread); + // // Pipe + // + + // Named Pipe for IPC between tsf and server std::thread pipe_worker(FanyNamedPipe::WorkerThread); std::thread pipe_listener(FanyNamedPipe::EventListenerLoopThread); + ::mainPipeThread = pipe_listener.native_handle(); + // Aux Named Pipe for reconnecting main pipe + std::thread aux_pipe_listener(FanyNamedPipe::AuxPipeEventListenerLoopThread); int ret = CreateCandidateWindow(hInstance); @@ -41,5 +48,7 @@ int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In pipe_worker.join(); pipe_listener.join(); + aux_pipe_listener.join(); + return ret; } \ No newline at end of file