Skip to content

Commit 2bc1c2d

Browse files
committed
V2025.6.4
1 parent 25df100 commit 2bc1c2d

File tree

6 files changed

+87
-64
lines changed

6 files changed

+87
-64
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## 2025.6.4
4+
### Breaking Changes
5+
None
6+
### New APIs
7+
None
8+
### Fixes
9+
#### System
10+
- Fixed an issue where `Process::pause()` and `Process::resume()` did not work correctly on Windows
11+
312
## 2025.6.3
413
### Breaking Changes
514
None

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ endif()
2020
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
2121

2222
#libnick Definition
23-
project ("libnick" LANGUAGES C CXX VERSION 2025.6.3 DESCRIPTION "A cross-platform base for native Nickvision applications.")
23+
project ("libnick" LANGUAGES C CXX VERSION 2025.6.4 DESCRIPTION "A cross-platform base for native Nickvision applications.")
2424
include(CMakePackageConfigHelpers)
2525
include(GNUInstallDirs)
2626
include(CTest)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,4 @@ A C++20 compiler is also required to build libnick.
9191
```
9292
find_package(libnick CONFIG REQUIRED)
9393
target_link_libraries(main PRIVATE libnick::libnick)
94-
```
94+
```

manual/README.md

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,36 @@
66

77
libnick provides Nickvision apps with a common set of cross-platform APIs for managing system and desktop app functionality such as network management, taskbar icons, translations, app updates, and more.
88

9-
## 2025.6.3
9+
## 2025.6.4
1010
### Breaking Changes
1111
None
1212
### New APIs
1313
None
1414
### Fixes
15-
- Fixed an issue with the cmake configuration file
15+
#### System
16+
- Fixed an issue where `Process::pause()` and `Process::resume()` did not work correctly on Windows
1617

1718
## Dependencies
18-
The following are a list of dependencies used by libnick.
19+
The following are a list of dependencies used by libnick.
20+
21+
The recommendation and below commands will use vcpkg to pull these dependencies. However, vcpkg is not a requirement as long as the system provides these dependencies correctly.
1922

2023
### All Platforms
2124
- boost-json
2225
- gtest
2326
- libcurl
2427
- libintl
2528
- maddy
29+
- sqlcipher (Must be provided by the system on Linux and macOS as sqlcipher is not available via vcpkg for these systems)
2630

27-
### Windows
28-
The above dependencies must be installed, *plus* the following for Windows systems:
29-
- sqlcipher
30-
31-
### Linux
32-
The above dependencies must be installed, *plus* the following for Linux systems:
31+
### Linux and macOS
32+
The above dependencies must be installed, *plus* the following for Linux and macOS systems:
3333
- glib
3434
- libsecret
35-
- openssl
36-
- Used for sqlcipher, as libnick manually builds sqlcipher on Linux as the vcpkg port is broken.
37-
38-
### macOS
39-
The above dependencies must be installed, *plus* the following for macOS systems:
40-
- glib
41-
- libsecret (Only required if `-DUSE_LIBSECRET="ON"`)
42-
- openssl
43-
- Used for sqlcipher, as libnick manually builds sqlcipher on macOS as the vcpkg port is broken.
35+
- For macOS: Only required if `-DUSE_LIBSECRET="ON"`
4436

4537
## Consuming libnick via vcpkg
46-
libnick is available through `vcpkg`.
38+
libnick is available through `vcpkg`.
4739

4840
Simply install and configure vcpkg for your system, and run:
4941
```
@@ -56,9 +48,9 @@ target_link_libraries(main PRIVATE libnick::libnick)
5648
```
5749

5850
## Building and Installing Manually
59-
libnick uses `vcpkg` to manage its dependencies and `cmake` as its build system.
51+
libnick uses `cmake` as its build system and `vcpkg` to *optionally* manage its dependencies.
6052

61-
Ensure both `vcpkg` and `cmake` are installed on your system before building and installing libnick.
53+
Ensure `cmake` and `vcpkg` are installed on your system before building and installing libnick.
6254

6355
A C++20 compiler is also required to build libnick.
6456

@@ -69,42 +61,39 @@ A C++20 compiler is also required to build libnick.
6961
1. Run `vcpkg install boost-json curl gettext-libintl gtest maddy sqlcipher`
7062
#### Linux
7163
1. Set the `VCPKG_DEFAULT_TRIPLET` environment variable to `x64-linux`
72-
1. Run `vcpkg install boost-json curl gettext-libintl glib gtest libsecret maddy openssl`
73-
#### macOS (Intel)
74-
1. Set the `VCPKG_DEFAULT_TRIPLET` environment variable to `x64-osx`
75-
1. Run `vcpkg install boost-json curl gettext-libintl glib gtest libsecret maddy openssl`
64+
1. Run `vcpkg install boost-json curl gettext-libintl glib gtest libsecret maddy`
7665
#### macOS (Apple Silicon)
7766
1. Set the `VCPKG_DEFAULT_TRIPLET` environment variable to `arm64-osx`
78-
1. Run `vcpkg install boost-json curl gettext-libintl glib gtest libsecret maddy openssl`
67+
1. Run `vcpkg install boost-json curl gettext-libintl glib gtest libsecret maddy`
7968

8069
### Building
8170
1. First, clone/download the repo.
8271
1. Open a terminal and navigate to the repo's root directory.
83-
1. Create a new `build` directory and `cd` into it.
72+
1. Create a new `build` directory and `cd` into it.
8473
#### Windows
8574
1. From the `build` folder, run `cmake .. -G "Visual Studio 17 2022"`.
86-
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
87-
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
75+
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
76+
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
8877
1. From the `build` folder, run `cmake --build . --config Release`.
8978
1. After these commands complete, libnick will be successfully built and its binaries can be found in the `Release` folder of the `build` folder.
9079
#### Linux
9180
1. From the `build` folder, run `cmake .. -DCMAKE_BUILD_TYPE=Release`.
92-
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
93-
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
81+
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
82+
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
9483
1. From the `build` folder, run `cmake --build .`.
9584
1. After these commands complete, libnick will be successfully built and its binaries can be found in the `build` folder.
9685
#### macOS
9786
1. From the `build` folder, run `cmake .. -DCMAKE_BUILD_TYPE=Release`.
98-
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
99-
- To use `libsecret` instead of macOS's built in security library, add `-DUSE_LIBSECRET="ON"` to the end of the command.
100-
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
87+
- To skip building libnick's test suite, add `-DBUILD_TESTING="OFF"` to the end of the command.
88+
- To use `libsecret` instead of macOS's built in security library, add `-DUSE_LIBSECRET="ON"` to the end of the command.
89+
- If you plan to install libnick, add `-DCMAKE_INSTALL_PREFIX=PATH_TO_INSTALL_DIR` to the end of the command, replacing `PATH_TO_INSTALL_DIR` with the path of where you'd like libnick to install to.
10190
1. From the `build` folder, run `cmake --build .`.
10291
1. After these commands complete, libnick will be successfully built and its binaries can be found in the `build` folder.
10392

10493
### Installing
10594
1. To install libnick to the system, from the `build` folder, run `cmake --install .`.
106-
- This command will export and install libnick cmake targets allowing you to simply use libnick in other cmake projects with the following:
107-
```
108-
find_package(libnick CONFIG REQUIRED)
109-
target_link_libraries(main PRIVATE libnick::libnick)
110-
```
95+
- This command will export and install libnick cmake targets allowing you to simply use libnick in other cmake projects with the following:
96+
```
97+
find_package(libnick CONFIG REQUIRED)
98+
target_link_libraries(main PRIVATE libnick::libnick)
99+
```

src/system/process.cpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -442,15 +442,28 @@ namespace Nickvision::System
442442
#ifndef _WIN32
443443
::kill(-m_pid, SIGCONT);
444444
if(::kill(m_pid, SIGCONT) < 0)
445-
#else
446-
if(!DebugActiveProcessStop(m_pi.dwProcessId))
447-
#endif
448-
449445
{
450446
return false;
451447
}
452-
#ifdef _WIN32
453-
DebugSetProcessKillOnExit(false);
448+
#else
449+
HANDLE snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) };
450+
THREADENTRY32 entry{ sizeof(THREADENTRY32) };
451+
if(Thread32First(snapshot, &entry))
452+
{
453+
do
454+
{
455+
if(entry.th32OwnerProcessID == m_pi.dwProcessId)
456+
{
457+
HANDLE thread{ OpenThread(THREAD_SUSPEND_RESUME, false, entry.th32ThreadID) };
458+
if(thread)
459+
{
460+
ResumeThread(thread);
461+
CloseHandle(thread);
462+
}
463+
}
464+
} while(Thread32Next(snapshot, &entry));
465+
}
466+
CloseHandle(snapshot);
454467
#endif
455468
m_state = ProcessState::Running;
456469
return true;
@@ -466,12 +479,29 @@ namespace Nickvision::System
466479
#ifndef _WIN32
467480
::kill(-m_pid, SIGSTOP);
468481
if(::kill(m_pid, SIGSTOP) < 0)
469-
#else
470-
if(!DebugActiveProcess(m_pi.dwProcessId))
471-
#endif
472482
{
473483
return false;
474484
}
485+
#else
486+
HANDLE snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0) };
487+
THREADENTRY32 entry{ sizeof(THREADENTRY32) };
488+
if(Thread32First(snapshot, &entry))
489+
{
490+
do
491+
{
492+
if(entry.th32OwnerProcessID == m_pi.dwProcessId)
493+
{
494+
HANDLE thread{ OpenThread(THREAD_SUSPEND_RESUME, false, entry.th32ThreadID) };
495+
if(thread)
496+
{
497+
SuspendThread(thread);
498+
CloseHandle(thread);
499+
}
500+
}
501+
} while(Thread32Next(snapshot, &entry));
502+
}
503+
CloseHandle(snapshot);
504+
#endif
475505
m_state = ProcessState::Paused;
476506
return true;
477507
}
@@ -513,12 +543,15 @@ namespace Nickvision::System
513543
#ifndef _WIN32
514544
int status{ 0 };
515545
#endif
516-
bool ended{ false };
517-
while(!ended)
546+
DWORD exitCode{ 0 };
547+
do
518548
{
519549
#ifdef _WIN32
520550
//Determine if ended
521-
ended = WaitForSingleObject(m_pi.hProcess, 0) == WAIT_OBJECT_0;
551+
if(!GetExitCodeProcess(m_pi.hProcess, &exitCode))
552+
{
553+
exitCode = STILL_ACTIVE;
554+
}
522555
//Read console output
523556
while(true)
524557
{
@@ -556,18 +589,10 @@ namespace Nickvision::System
556589
}
557590
#endif
558591
std::this_thread::sleep_for(std::chrono::milliseconds(PROCESS_WAIT_TIMEOUT));
559-
}
592+
} while(exitCode == STILL_ACTIVE);
560593
std::unique_lock<std::mutex> lock{ m_mutex };
561594
#ifdef _WIN32
562-
DWORD exitCode{ 0 };
563-
if(GetExitCodeProcess(m_pi.hProcess, &exitCode))
564-
{
565-
m_exitCode = static_cast<int>(exitCode);
566-
}
567-
else
568-
{
569-
m_exitCode = -1;
570-
}
595+
m_exitCode = static_cast<int>(exitCode);
571596
#else
572597
m_exitCode = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
573598
#endif

tests/processtests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ std::unique_ptr<Process> ProcessTest::m_proc{ nullptr };
1616
TEST_F(ProcessTest, Create)
1717
{
1818
#ifdef _WIN32
19-
ASSERT_NO_THROW(m_proc = std::make_unique<Process>(Environment::findDependency("cmd.exe"), std::vector<std::string>{ "/c", "start", "/min", "timeout.exe", "60" }));
19+
ASSERT_NO_THROW(m_proc = std::make_unique<Process>(Environment::findDependency("cmd.exe"), std::vector<std::string>{ "/c", "ping -n 60 127.0.0.1" }));
2020
#else
2121
ASSERT_NO_THROW(m_proc = std::make_unique<Process>(Environment::findDependency("sleep"), std::vector<std::string>{ "60" }));
2222
#endif

0 commit comments

Comments
 (0)