Skip to content

Commit 264608b

Browse files
committed
Testing with threads instead of processes under Windows.
1 parent 8c64330 commit 264608b

File tree

5 files changed

+115
-6
lines changed

5 files changed

+115
-6
lines changed

README.md

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

src/libipc/CMakeLists.txt

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ if(NOT MSVC)
55
-Wno-attributes)
66
endif()
77

8+
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
9+
# FetchContent_Declare(phnt
10+
# GIT_REPOSITORY https://github.com/winsiderss/phnt.git
11+
# GIT_TAG master
12+
# )
13+
# FetchContent_MakeAvailable(phnt)
14+
# endif()
15+
816
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
917

1018
file(GLOB HEAD_FILES
@@ -47,6 +55,10 @@ else()
4755
target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr)
4856
endif()
4957

58+
# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
59+
# target_link_libraries(${PROJECT_NAME} PUBLIC phnt)
60+
# endif()
61+
5062
install(
5163
TARGETS ${PROJECT_NAME}
5264
RUNTIME DESTINATION bin
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* \file libipc/platform/win/process_impl.h
3+
* \author mutouyun (orz@orzz.org)
4+
*/
5+
#pragma once
6+
7+
#include <phnt_windows.h>
8+
#include <phnt.h>
9+
10+
#include "libimp/log.h"
11+
#include "libipc/process.h"
12+
13+
LIBIPC_NAMESPACE_BEG_
14+
using namespace ::LIBIMP;
15+
16+
/// \brief Experimental fork() on Windows.
17+
/// \see https://gist.github.com/Cr4sh/126d844c28a7fbfd25c6
18+
/// https://github.com/huntandhackett/process-cloning
19+
namespace {
20+
21+
typedef SSIZE_T pid_t;
22+
23+
pid_t fork() {
24+
LIBIMP_LOG_();
25+
26+
RTL_USER_PROCESS_INFORMATION process_info;
27+
NTSTATUS status;
28+
29+
/* lets do this */
30+
status = RtlCloneUserProcess(RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES
31+
, NULL, NULL, NULL, &process_info);
32+
if (status == STATUS_PROCESS_CLONED) {
33+
// Executing inside the clone...
34+
// Re-attach to the parent's console to be able to write to it
35+
FreeConsole();
36+
AttachConsole(ATTACH_PARENT_PROCESS);
37+
return 0;
38+
} else {
39+
// Executing inside the original (parent) process...
40+
if (!NT_SUCCESS(status)) {
41+
log.error("failed: RtlCloneUserProcess(...)");
42+
return -1;
43+
}
44+
return (pid_t)process_info.ProcessHandle;
45+
}
46+
47+
/* NOTREACHED */
48+
}
49+
50+
#define WNOHANG 1 /* Don't block waiting. */
51+
52+
/// \see https://man7.org/linux/man-pages/man3/wait.3p.html
53+
/// https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntwaitforsingleobject
54+
pid_t waitpid(pid_t pid, int */*status*/, int options) {
55+
LIBIMP_LOG_();
56+
if (pid == -1) {
57+
return -1;
58+
}
59+
if (options & WNOHANG) {
60+
return pid;
61+
}
62+
NTSTATUS status = NtWaitForSingleObject((HANDLE)pid, FALSE, NULL);
63+
if (!NT_SUCCESS(status)) {
64+
log.error("failed: NtWaitForSingleObject(...)");
65+
return -1;
66+
}
67+
return pid;
68+
}
69+
70+
} // namespace
71+
LIBIPC_NAMESPACE_END_

test/ipc/test_ipc_shm.cpp

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "libipc/shm.h"
55

6+
#include "test_util.h"
7+
68
TEST(shm, open_close) {
79
EXPECT_FALSE(ipc::shm_open("hello-ipc-shm", 1024, ipc::mode::none));
810

@@ -76,6 +78,22 @@ TEST(shm, shared_memory) {
7678
EXPECT_TRUE(ipc::shm_close(*shm_r));
7779
}
7880

81+
TEST(shm, process) {
82+
ipc::shared_memory shm{"ipc-shared-memory-process1", 333};
83+
ASSERT_TRUE(shm.valid());
84+
*shm.as<int>() = 4321;
85+
86+
auto r1 = test::subproc([] {
87+
ipc::shared_memory shm{"ipc-shared-memory-process1"};
88+
ASSERT_TRUE(shm.valid());
89+
EXPECT_EQ(*shm.as<int>(), 4321);
90+
*shm.as<int>() = 1234;
91+
});
92+
93+
test::join_subproc(r1);
94+
EXPECT_EQ(*shm.as<int>(), 1234);
95+
}
96+
7997
#include <libimp/detect_plat.h>
8098
#if /*defined(LIBIMP_OS_LINUX)*/ 0
8199
#include <sys/socket.h>
@@ -87,8 +105,6 @@ TEST(shm, shared_memory) {
87105
#include <unistd.h>
88106
#include <fcntl.h>
89107

90-
#include "test_util.h"
91-
92108
TEST(shm, pipe) {
93109
auto writer = test::subproc([] {
94110
mkfifo("/tmp/shm-pipe.w", S_IFIFO|0666);

test/test_util.h

+14-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
# include <sys/wait.h>
77
# include <unistd.h>
88
#else
9-
# define pid_t int
9+
# include <Windows.h>
10+
# include <process.h>
11+
# define pid_t uintptr_t
1012
#endif
1113

1214
#include <condition_variable>
@@ -15,7 +17,7 @@
1517
namespace test {
1618

1719
template <typename Fn>
18-
pid_t subproc(Fn&& fn) {
20+
pid_t subproc(Fn &&fn) {
1921
#ifndef LIBIMP_OS_WIN
2022
pid_t pid = fork();
2123
if (pid == -1) {
@@ -31,14 +33,23 @@ pid_t subproc(Fn&& fn) {
3133
}
3234
return pid;
3335
#else
34-
return -1;
36+
auto runner = [](void* pparam) {
37+
auto fn = reinterpret_cast<std::decay_t<Fn> *>(pparam);
38+
(*fn)();
39+
};
40+
return _beginthread(runner, 0, (void *)&fn);
3541
#endif
3642
}
3743

3844
inline void join_subproc(pid_t pid) {
45+
if (pid == -1) return;
3946
#ifndef LIBIMP_OS_WIN
4047
int ret_code;
4148
waitpid(pid, &ret_code, 0);
49+
#else
50+
HANDLE hThread = reinterpret_cast<HANDLE>(pid);
51+
WaitForSingleObject(hThread, INFINITE);
52+
CloseHandle(hThread);
4253
#endif
4354
}
4455

0 commit comments

Comments
 (0)