Skip to content

Commit b5f76b5

Browse files
committed
Fixed Linux implementation to read size from shared memory
1 parent 859a4d4 commit b5f76b5

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# v1.1.0.1 - 2025-10-21
2+
- Fixed Linux implementation to read size from shared memory when opening existing segments
3+
- Added size validation when opening existing shared memory with size mismatch
4+
15
# v1.1.0.0 - 2025-10-04
26
- Fixed size calculation in shared memory mapping to use reserved_info struct
37
- Added server-client shared memory test case

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.10)
22

3-
set(BUILD_VERSION 1.1.0.0)
3+
set(BUILD_VERSION 1.1.0.1)
44

55
project(slick_queue
66
VERSION ${BUILD_VERSION}

include/slick_queue/slick_queue.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,19 @@ class SlickQueue {
411411

412412
if (err != ERROR_ALREADY_EXISTS) {
413413
own_ = true;
414+
} else {
415+
// Shared memory already exists, need to read and validate size
416+
auto lpvMem = MapViewOfFile(hMapFile_, FILE_MAP_ALL_ACCESS, 0, 0, 64);
417+
if (!lpvMem) {
418+
auto err = GetLastError();
419+
throw std::runtime_error("Failed to map shm for size read. err=" + std::to_string(err));
420+
}
421+
uint32_t shm_size = *reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(lpvMem) + sizeof(std::atomic<reserved_info>));
422+
UnmapViewOfFile(lpvMem);
423+
424+
if (shm_size != size_) {
425+
throw std::runtime_error("Shared memory size mismatch. Expected " + std::to_string(size_) + " but got " + std::to_string(shm_size));
426+
}
414427
}
415428
}
416429

@@ -434,7 +447,7 @@ class SlickQueue {
434447
}
435448
#else
436449
void allocate_shm_data(const char* const shm_name, bool open_only) {
437-
size_t BF_SZ = 64 + sizeof(slot) * size_ + sizeof(T) * size_;
450+
size_t BF_SZ;
438451
shm_name_ = shm_name;
439452
int flags = open_only ? O_RDWR : (O_RDWR | O_CREAT | O_EXCL);
440453
shm_fd_ = shm_open(shm_name, flags, 0666);
@@ -446,13 +459,38 @@ class SlickQueue {
446459
throw std::runtime_error("Failed to open existing shm. err=" + std::to_string(errno));
447460
}
448461
own_ = false;
462+
463+
// Read size from shared memory and verify it matches
464+
void* temp_map = mmap(nullptr, 64, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0);
465+
if (temp_map == MAP_FAILED) {
466+
throw std::runtime_error("Failed to map shm for size read. err=" + std::to_string(errno));
467+
}
468+
uint32_t shm_size = *reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(temp_map) + sizeof(std::atomic<reserved_info>));
469+
munmap(temp_map, 64);
470+
471+
if (shm_size != size_) {
472+
throw std::runtime_error("Shared memory size mismatch. Expected " + std::to_string(size_) + " but got " + std::to_string(shm_size));
473+
}
449474
} else {
450475
throw std::runtime_error("Failed to open/create shm. err=" + std::to_string(errno));
451476
}
452477
} else {
453478
own_ = !open_only;
454479
}
455480

481+
if (open_only) {
482+
// Map first 64 bytes to read the size
483+
void* temp_map = mmap(nullptr, 64, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd_, 0);
484+
if (temp_map == MAP_FAILED) {
485+
throw std::runtime_error("Failed to map shm for size read. err=" + std::to_string(errno));
486+
}
487+
size_ = *reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(temp_map) + sizeof(std::atomic<reserved_info>));
488+
mask_ = size_ - 1;
489+
munmap(temp_map, 64);
490+
}
491+
492+
BF_SZ = 64 + sizeof(slot) * size_ + sizeof(T) * size_;
493+
456494
if (own_) {
457495
if (ftruncate(shm_fd_, BF_SZ) == -1) {
458496
throw std::runtime_error("Failed to size shm. err=" + std::to_string(errno));

tests/shm_tests.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,13 @@ TEST_CASE( "Atomic cursor - shared memory work-stealing" ) {
150150
REQUIRE(total_consumed.load() == 100);
151151
REQUIRE(shared_cursor.load() == 100);
152152
}
153+
154+
TEST_CASE( "Size mismatch - shm" ) {
155+
// Create a shared memory queue with size 4
156+
SlickQueue<int> server(4, "sq_size_mismatch");
157+
158+
// Try to create another queue with same name but different size
159+
// This should throw an exception
160+
REQUIRE_THROWS_WITH(SlickQueue<int>(8, "sq_size_mismatch"),
161+
Catch::Matchers::Contains("Shared memory size mismatch"));
162+
}

0 commit comments

Comments
 (0)