Skip to content

Commit

Permalink
Testing with threads instead of processes under Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
mutouyun committed Sep 1, 2024
1 parent 8c64330 commit 264608b
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 6 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ A high-performance inter-process communication using shared memory on Linux/Wind
- [ ] IPC:实现基本组件
- [x] 共享内存(需要作为后续组件的基础)
- [x] 原子锁
- [ ] 进程对象
- [ ] 互斥量
- [ ] 条件变量
- [ ] 信号量
Expand Down
12 changes: 12 additions & 0 deletions src/libipc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ if(NOT MSVC)
-Wno-attributes)
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)

file(GLOB HEAD_FILES
Expand Down Expand Up @@ -47,6 +55,10 @@ else()
target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr)
endif()

# if(CMAKE_SYSTEM_NAME MATCHES "Windows")
# target_link_libraries(${PROJECT_NAME} PUBLIC phnt)
# endif()

install(
TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
Expand Down
71 changes: 71 additions & 0 deletions src/libipc/platform/win/process_impl.h
Original file line number Diff line number Diff line change
@@ -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_
20 changes: 18 additions & 2 deletions test/ipc/test_ipc_shm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "libipc/shm.h"

#include "test_util.h"

TEST(shm, open_close) {
EXPECT_FALSE(ipc::shm_open("hello-ipc-shm", 1024, ipc::mode::none));

Expand Down Expand Up @@ -76,6 +78,22 @@ TEST(shm, shared_memory) {
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>
#if /*defined(LIBIMP_OS_LINUX)*/ 0
#include <sys/socket.h>
Expand All @@ -87,8 +105,6 @@ TEST(shm, shared_memory) {
#include <unistd.h>
#include <fcntl.h>

#include "test_util.h"

TEST(shm, pipe) {
auto writer = test::subproc([] {
mkfifo("/tmp/shm-pipe.w", S_IFIFO|0666);
Expand Down
17 changes: 14 additions & 3 deletions test/test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
# include <sys/wait.h>
# include <unistd.h>
#else
# define pid_t int
# include <Windows.h>
# include <process.h>
# define pid_t uintptr_t
#endif

#include <condition_variable>
Expand All @@ -15,7 +17,7 @@
namespace test {

template <typename Fn>
pid_t subproc(Fn&& fn) {
pid_t subproc(Fn &&fn) {
#ifndef LIBIMP_OS_WIN
pid_t pid = fork();
if (pid == -1) {
Expand All @@ -31,14 +33,23 @@ pid_t subproc(Fn&& fn) {
}
return pid;
#else
return -1;
auto runner = [](void* pparam) {
auto fn = reinterpret_cast<std::decay_t<Fn> *>(pparam);
(*fn)();
};
return _beginthread(runner, 0, (void *)&fn);
#endif
}

inline void join_subproc(pid_t pid) {
if (pid == -1) return;
#ifndef LIBIMP_OS_WIN
int ret_code;
waitpid(pid, &ret_code, 0);
#else
HANDLE hThread = reinterpret_cast<HANDLE>(pid);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
#endif
}

Expand Down

0 comments on commit 264608b

Please sign in to comment.