Skip to content

Commit be15a7c

Browse files
committed
Fix race condition; add release workflow
1 parent 8be2890 commit be15a7c

File tree

3 files changed

+109
-31
lines changed

3 files changed

+109
-31
lines changed

.github/workflows/release.yml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Create Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Trigger on version tags like v0.1.0, v1.0.0, etc.
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
create-release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Extract version from tag
19+
id: get_version
20+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
21+
22+
- name: Extract changelog for this version
23+
id: changelog
24+
run: |
25+
if [ -f CHANGELOG ]; then
26+
# Extract the section for this version from CHANGELOG
27+
VERSION="${{ github.ref_name }}"
28+
# Escape dots in version for regex
29+
VERSION_ESCAPED=$(echo "$VERSION" | sed 's/\./\\./g')
30+
# Use awk to extract content: start at version header, stop at next ## header
31+
CHANGES=$(awk "BEGIN{p=0} /^# $VERSION_ESCAPED/{p=1;next} /^# /{p=0} p" CHANGELOG | sed '/^$/d')
32+
33+
if [ -z "$CHANGES" ]; then
34+
echo "CHANGELOG_CONTENT=No changelog entry found for this version." >> $GITHUB_OUTPUT
35+
else
36+
# Escape newlines for GitHub output
37+
echo "CHANGELOG_CONTENT<<EOF" >> $GITHUB_OUTPUT
38+
echo "$CHANGES" >> $GITHUB_OUTPUT
39+
echo "EOF" >> $GITHUB_OUTPUT
40+
fi
41+
else
42+
echo "CHANGELOG_CONTENT=CHANGELOG not found." >> $GITHUB_OUTPUT
43+
fi
44+
45+
- name: Create header archive
46+
run: |
47+
cd include
48+
zip -r ../slick_shm-${{ steps.get_version.outputs.VERSION }}-headers.zip slick/
49+
cd ..
50+
51+
- name: Create Release
52+
uses: softprops/action-gh-release@v1
53+
with:
54+
name: Release ${{ github.ref_name }}
55+
body: |
56+
## Changes
57+
58+
${{ steps.changelog.outputs.CHANGELOG_CONTENT }}
59+
60+
draft: true
61+
prerelease: false
62+
generate_release_notes: false
63+
files: |
64+
slick_shm-${{ steps.get_version.outputs.VERSION }}-headers.zip

CMakeLists.txt

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ endif()
2020

2121
option(BUILD_SLICK_QUEUE_TESTS "Build tests" ON)
2222
if(BUILD_SLICK_QUEUE_TESTS)
23+
enable_testing()
2324
if (WIN32)
2425
add_subdirectory(tests)
2526
else()
@@ -68,33 +69,33 @@ install(EXPORT slick_queueTargets
6869

6970
message(STATUS "slick_queue: ${PROJECT_VERSION}")
7071

71-
# Automatically run install after build in Release mode
72-
if(CMAKE_BUILD_TYPE STREQUAL "Release")
73-
add_custom_target(dist_slick_queue ALL
74-
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/dist/include
75-
COMMENT "Copying slick_queue headers to dist/include"
76-
VERBATIM
77-
)
78-
79-
if (MSVC)
80-
set_target_properties(dist_slick_queue PROPERTIES
81-
VS_GLOBAL_IntDir "$(Platform)\\$(Configuration)\\dist_slick_queue\\"
82-
)
83-
endif()
84-
85-
if (PROJECT_IS_TOP_LEVEL)
86-
add_custom_target(package_slick_queue ALL
87-
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${CMAKE_BINARY_DIR}/dist/slick_queue_${PROJECT_VERSION}.zip" --format=zip "${CMAKE_CURRENT_SOURCE_DIR}/include"
88-
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
89-
COMMENT "Creating zip archive"
90-
)
91-
add_dependencies(package_slick_queue dist_slick_queue)
92-
93-
if (MSVC)
94-
set_target_properties(package_slick_queue PROPERTIES
95-
VS_GLOBAL_IntDir "$(Platform)\\$(Configuration)\\package_slick_queue\\"
96-
)
97-
endif()
98-
endif()
99-
endif()
72+
# # Automatically run install after build in Release mode
73+
# if(CMAKE_BUILD_TYPE STREQUAL "Release")
74+
# add_custom_target(dist_slick_queue ALL
75+
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/dist/include
76+
# COMMENT "Copying slick_queue headers to dist/include"
77+
# VERBATIM
78+
# )
79+
80+
# if (MSVC)
81+
# set_target_properties(dist_slick_queue PROPERTIES
82+
# VS_GLOBAL_IntDir "$(Platform)\\$(Configuration)\\dist_slick_queue\\"
83+
# )
84+
# endif()
85+
86+
# if (PROJECT_IS_TOP_LEVEL)
87+
# add_custom_target(package_slick_queue ALL
88+
# COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${CMAKE_BINARY_DIR}/dist/slick_queue_${PROJECT_VERSION}.zip" --format=zip "${CMAKE_CURRENT_SOURCE_DIR}/include"
89+
# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
90+
# COMMENT "Creating zip archive"
91+
# )
92+
# add_dependencies(package_slick_queue dist_slick_queue)
93+
94+
# if (MSVC)
95+
# set_target_properties(package_slick_queue PROPERTIES
96+
# VS_GLOBAL_IntDir "$(Platform)\\$(Configuration)\\package_slick_queue\\"
97+
# )
98+
# endif()
99+
# endif()
100+
# endif()
100101

include/slick/queue.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <stdexcept>
1717
#include <string>
1818
#include <cassert>
19+
#include <thread>
20+
#include <chrono>
1921

2022
#if defined(_MSC_VER)
2123
#ifndef NOMINMAX
@@ -364,9 +366,10 @@ class SlickQueue {
364366
#ifndef UNICODE
365367
std::string shmName = shm_name;
366368
#else
367-
int size_needed = MultiByteToWideChar(CP_UTF8, 0, shm_name, static_cast<int>(strlen(shm_name)), NULL, 0);
369+
int shm_name_sz = static_cast<int>(strlen(shm_name));
370+
int size_needed = MultiByteToWideChar(CP_UTF8, 0, shm_name, shm_name_sz, NULL, 0);
368371
std::wstring shmName(size_needed, 0);
369-
MultiByteToWideChar(CP_UTF8, 0, shm_name, strlen(shm_name), &shmName[0], size_needed);
372+
MultiByteToWideChar(CP_UTF8, 0, shm_name, shm_name_sz, &shmName[0], size_needed);
370373
#endif
371374

372375
if (open_only) {
@@ -425,6 +428,11 @@ class SlickQueue {
425428
if (err != ERROR_ALREADY_EXISTS) {
426429
own_ = true;
427430
} else {
431+
// when multiple process trying to create the same shared memory segment,
432+
// there is a chance that the segment is created but not yet initialized.
433+
// so we need to wait until the segment is initialized.
434+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
435+
428436
// Shared memory already exists, need to read and validate size
429437
auto lpvMem = MapViewOfFile(hMapFile_, FILE_MAP_ALL_ACCESS, 0, 0, HEADER_SIZE);
430438
if (!lpvMem) {
@@ -481,6 +489,11 @@ class SlickQueue {
481489
}
482490
own_ = false;
483491

492+
// when multiple process trying to create the same shared memory segment,
493+
// there is a chance that the segment is created but not yet initialized.
494+
// so we need to wait until the segment is initialized.
495+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
496+
484497
// Read size from shared memory and verify it matches
485498
void* temp_map = mmap(nullptr, HEADER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0);
486499
if (temp_map == MAP_FAILED) {

0 commit comments

Comments
 (0)