Testing with threads instead of processes under Windows.

This commit is contained in:
mutouyun 2024-09-01 19:05:02 +08:00
parent 8c643308dd
commit 264608b621
5 changed files with 115 additions and 6 deletions

View File

@ -21,7 +21,6 @@ A high-performance inter-process communication using shared memory on Linux/Wind
- [ ] IPC实现基本组件 - [ ] IPC实现基本组件
- [x] 共享内存(需要作为后续组件的基础) - [x] 共享内存(需要作为后续组件的基础)
- [x] 原子锁 - [x] 原子锁
- [ ] 进程对象
- [ ] 互斥量 - [ ] 互斥量
- [ ] 条件变量 - [ ] 条件变量
- [ ] 信号量 - [ ] 信号量

View File

@ -5,6 +5,14 @@ if(NOT MSVC)
-Wno-attributes) -Wno-attributes)
endif() endif()
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
# FetchContent_Declare(phnt
# GIT_REPOSITORY https://github.com/winsiderss/phnt.git
# GIT_TAG master
# )
# FetchContent_MakeAvailable(phnt)
# endif()
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES) aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
file(GLOB HEAD_FILES file(GLOB HEAD_FILES
@ -47,6 +55,10 @@ else()
target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr) target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr)
endif() endif()
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
# target_link_libraries(${PROJECT_NAME} PUBLIC phnt)
# endif()
install( install(
TARGETS ${PROJECT_NAME} TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin RUNTIME DESTINATION bin

View File

@ -0,0 +1,71 @@
/**
* \file libipc/platform/win/process_impl.h
* \author mutouyun (orz@orzz.org)
*/
#pragma once
#include <phnt_windows.h>
#include <phnt.h>
#include "libimp/log.h"
#include "libipc/process.h"
LIBIPC_NAMESPACE_BEG_
using namespace ::LIBIMP;
/// \brief Experimental fork() on Windows.
/// \see https://gist.github.com/Cr4sh/126d844c28a7fbfd25c6
/// https://github.com/huntandhackett/process-cloning
namespace {
typedef SSIZE_T pid_t;
pid_t fork() {
LIBIMP_LOG_();
RTL_USER_PROCESS_INFORMATION process_info;
NTSTATUS status;
/* lets do this */
status = RtlCloneUserProcess(RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES
, NULL, NULL, NULL, &process_info);
if (status == STATUS_PROCESS_CLONED) {
// Executing inside the clone...
// Re-attach to the parent's console to be able to write to it
FreeConsole();
AttachConsole(ATTACH_PARENT_PROCESS);
return 0;
} else {
// Executing inside the original (parent) process...
if (!NT_SUCCESS(status)) {
log.error("failed: RtlCloneUserProcess(...)");
return -1;
}
return (pid_t)process_info.ProcessHandle;
}
/* NOTREACHED */
}
#define WNOHANG 1 /* Don't block waiting. */
/// \see https://man7.org/linux/man-pages/man3/wait.3p.html
/// https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntwaitforsingleobject
pid_t waitpid(pid_t pid, int */*status*/, int options) {
LIBIMP_LOG_();
if (pid == -1) {
return -1;
}
if (options & WNOHANG) {
return pid;
}
NTSTATUS status = NtWaitForSingleObject((HANDLE)pid, FALSE, NULL);
if (!NT_SUCCESS(status)) {
log.error("failed: NtWaitForSingleObject(...)");
return -1;
}
return pid;
}
} // namespace
LIBIPC_NAMESPACE_END_

View File

@ -3,6 +3,8 @@
#include "libipc/shm.h" #include "libipc/shm.h"
#include "test_util.h"
TEST(shm, open_close) { TEST(shm, open_close) {
EXPECT_FALSE(ipc::shm_open("hello-ipc-shm", 1024, ipc::mode::none)); EXPECT_FALSE(ipc::shm_open("hello-ipc-shm", 1024, ipc::mode::none));
@ -76,6 +78,22 @@ TEST(shm, shared_memory) {
EXPECT_TRUE(ipc::shm_close(*shm_r)); EXPECT_TRUE(ipc::shm_close(*shm_r));
} }
TEST(shm, process) {
ipc::shared_memory shm{"ipc-shared-memory-process1", 333};
ASSERT_TRUE(shm.valid());
*shm.as<int>() = 4321;
auto r1 = test::subproc([] {
ipc::shared_memory shm{"ipc-shared-memory-process1"};
ASSERT_TRUE(shm.valid());
EXPECT_EQ(*shm.as<int>(), 4321);
*shm.as<int>() = 1234;
});
test::join_subproc(r1);
EXPECT_EQ(*shm.as<int>(), 1234);
}
#include <libimp/detect_plat.h> #include <libimp/detect_plat.h>
#if /*defined(LIBIMP_OS_LINUX)*/ 0 #if /*defined(LIBIMP_OS_LINUX)*/ 0
#include <sys/socket.h> #include <sys/socket.h>
@ -87,8 +105,6 @@ TEST(shm, shared_memory) {
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "test_util.h"
TEST(shm, pipe) { TEST(shm, pipe) {
auto writer = test::subproc([] { auto writer = test::subproc([] {
mkfifo("/tmp/shm-pipe.w", S_IFIFO|0666); mkfifo("/tmp/shm-pipe.w", S_IFIFO|0666);

View File

@ -6,7 +6,9 @@
# include <sys/wait.h> # include <sys/wait.h>
# include <unistd.h> # include <unistd.h>
#else #else
# define pid_t int # include <Windows.h>
# include <process.h>
# define pid_t uintptr_t
#endif #endif
#include <condition_variable> #include <condition_variable>
@ -31,14 +33,23 @@ pid_t subproc(Fn&& fn) {
} }
return pid; return pid;
#else #else
return -1; auto runner = [](void* pparam) {
auto fn = reinterpret_cast<std::decay_t<Fn> *>(pparam);
(*fn)();
};
return _beginthread(runner, 0, (void *)&fn);
#endif #endif
} }
inline void join_subproc(pid_t pid) { inline void join_subproc(pid_t pid) {
if (pid == -1) return;
#ifndef LIBIMP_OS_WIN #ifndef LIBIMP_OS_WIN
int ret_code; int ret_code;
waitpid(pid, &ret_code, 0); waitpid(pid, &ret_code, 0);
#else
HANDLE hThread = reinterpret_cast<HANDLE>(pid);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
#endif #endif
} }