boostorg / interprocess Goto Github PK
View Code? Open in Web Editor NEWBoost.org interprocess module
Home Page: http://boost.org/libs/interprocess
Boost.org interprocess module
Home Page: http://boost.org/libs/interprocess
current default implementation use BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION macro,
#include <boost/interprocess/sync/shm/named_mutex.hpp> may deadlock when ower dead
#include <boost/interprocess/sync/posix/named_mutex.hpp> is the posix semaphore, it may also deadlock when ower dead.
why not change the named_mutx.hpp to mutex.hpp? using robust pthread_mutex
I see interprocess_mutex have been robust
boost_1_65_1 boost::unordered_map in shared_memory , insert、delete、find at random 0~10milliion times in 3 threads, but it crash in rbtree_best_fit, I used windows mutex to sync
Using clang on Windows (clang-cl), code that uses Boost.Interprocess fails without BOOST_USE_WINDOWS_H defined because it causes an overload resolution conflict between extern "C" functions declared inside namespaces vs at global scope. So the forward declarations of the Windows API functions in boost::interprocess::winapi end up conflicting with the declarations that do show up when someone includes both boost interprocess and windows.h itself.
This problem showed up in Boost.DateTime as well but it was subsequently fixed by boostorg/date_time#45 via use of Boost.WinAPI instead of its own hand rolled redeclarations. In Boost.WinAPI, we avoid this problem by ensuring that the Windows API declarations are at the global scope but still retain the namespaced winapi methods that call the global ones.
Can this be fixed? Thanks!
Came across this one while viewing old TRAC bugs. It's pretty recent and I assume the poster didn't know to put it here (and they are anonymous) so... here's the text:
Our security team has flagged: if(SetSecurityDescriptorDacl(&sd, true, 0, false)) in interprocess\detail\win32_api.hpp as a "high-priority" vulnerability
They then reference some of the text from the C6248 warning which says in part:
Objects that have null DACLs can have their security descriptors altered by malicious users so that no one has access to the object.
Even if everyone needs access to an object, the object should be secured so that only administrators can alter its security. If only the creator needs access to an object, a DACL should not be set on the object; the system will choose an appropriate default.
Looks like this could be fixed with a little research if someone was available to do the work.
Hello,
I have problem with Boost Interprocess. I create C DLL Library which I Marshall from C to C#.
I described problem in StackOwerflow
Is this behaviour bug or my fault? What i'm doing wrong?
when using interprocess shared memroy, there are about two locks. one is the internal mutex_family used by boost for managing the sharedmemory in MemoryAlgorithm, one is the user's one for synchronation. both mutex will cause deadlock, when process crash. How do you think about it.
the linux provide pthread_mutexattr_setrobust, but the interprocess module do not provide the interface, eg. interprocess:scoped_lock's lock's return value is void instead of int, which could be compare with EOWNERDEAD.
Hi!
In current implementation message_queue checks supplied buffer size against maximum possible message size, not against the current message size.
Moving check to place, where size of next object is already known would allow user to increase the allocated size only when needed. This would help limit memory allocation in case of queue sending messages of very different sizes.
I haven't been able to get named_condition_any objects to work on Linux with Boost 1.68.0. Below is code to replicate. When using a named_condition_any the child process will never receive the notification, when using just a named_condition the child process receives the notifications.
#include <boost/interprocess/sync/named_condition_any.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/thread/thread_time.hpp>
#include <unistd.h>
#include <chrono>
#include <thread>
#include <iostream>
namespace ip = boost::interprocess;
int main()
{
typedef ip::named_mutex mutex_type;
//typedef ip::named_condition condition_type;
typedef ip::named_condition_any condition_type;
mutex_type::remove("test_mutex");
condition_type::remove("test_condition");
pid_t pid = fork();
if(pid == 0)
{ // parent process
mutex_type mutex(ip::open_or_create, "test_mutex");
condition_type condition(ip::open_or_create, "test_condition");
while(true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "signaling children" << std::endl;
condition.notify_all();
}
}
else if(pid > 0)
{ // child process
mutex_type mutex(ip::open_or_create, "test_mutex");
condition_type condition(ip::open_or_create, "test_condition");
while(true)
{
boost::posix_time::ptime wait_time(boost::get_system_time() +
boost::posix_time::seconds(10));
ip::scoped_lock<ip::named_mutex> lock(mutex);
if(condition.timed_wait(lock, wait_time))
std::cout << "got signal from parent" << std::endl;
else
std::cout << "timeout" << std::endl;
}
}
else
{
std::cout << "failed to fork: " << pid << std::endl;
return 1;
}
return 0;
}
Hi!
When using a named_mutex within POSIX, and setting the Permissions Object, everything boils down to an ::sem_open call. There, the permissions are passed. But ::sem_open masks the permissions with the processes umask. Therefore, the semaphore might not have 0666 permissions, but e.g. 644, even though, permissions were passed with set_unrestricted().
Workaround there would be setting umask to 0 before ::sem_open, and restoring again after.
At least, this behaviour should be documented.
Regards,
Matthias
Hi,
I am trying to use boost
shared_memory_object
to write data to a block of memory from one .cpp file (with main section). Then, from another .cpp file (with main section), I want to read it. I tried example 33.6 in this . I am using cmake to build it in ubuntu. Boost version 1.54 is there in /usr/include
of my system. Following is the CMakeLists.txt
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
project (test1)
cmake_minimum_required (VERSION 2.8)
FIND_PACKAGE( Boost REQUIRED COMPONENTS system )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
add_executable(Power2 main.cpp)
TARGET_LINK_LIBRARIES( Power2 LINK_PUBLIC ${Boost_LIBRARIES} )
But while building either using Qt or cmake followed by make, I get following error. In functionboost::interprocess::shared_memory_object::priv_open_or_create(boost::interprocess:: ipcdetail:: create_enum_t, char const*, boost::interprocess::mode_t, boost::interprocess::permissions const&)':
Then, undefined reference to shm_open
and undefined reference to shm_unlink
I am unable to understand the source of the problem. Please look into it and help me out of the problem.
Boost Version : 1.71
By default when try to add interprocess header files, exceptions are enabled by default and it cannot be disabled with any preprocessor or configuration.
In Boost, there is a preprocessor defined BOOST_NO_EXCEPTIONS
which used in many other places. If user does not want to implement exception handling in their project and do not want to add flag like -fexceptions
, it has to be configurable in one of the config files.
So, before adding <boost/interprocess/exceptions.hpp>
header file in the interprocess component, it has to be checked before BOOST_NO_EXCEPTIONS
was defined in config files.
I looked deeply a little bit more on implementation and there is an inconsistency between exception handling in interprocess files. In some of them, problem was solved by adding no_exceptions_support.hpp
, please take a look on segment_manager.hpp
However, the other files has to be considered as well and common solution has to be used.
My proposal is, with checking BOOST_NO_EXCEPTIONS
compiler has to choose which file is included (in this case <boost/interprocess/exceptions.hpp>
and #include <boost/core/no_exceptions_support.hpp>
).
Also default keywords ( try
, catch
, throw
) has to be replaced with corresponding preprocessor definitions such as ( BOOST_TRY
, BOOST_CATCH
, BOOST_RETHROW
)
#0 0xbaf83a4 in void boost::interprocess::simple_swap<boost::interprocess::mode_t>(boost::interprocess::mode_t&, boost::interprocess::mode_t&) boost-1.67.0/include/boost/interprocess/detail/simple_swap.hpp:25:18
#1 0xbaf6f29 in boost::interprocess::ipcdetail::file_wrapper::swap(boost::interprocess::ipcdetail::file_wrapper&) boost-1.67.0/include/boost/interprocess/detail/file_wrapper.hpp:136:4
#2 0xbaf628f in void boost::interprocess::ipcdetail::managed_open_or_create_impl<boost::interprocess::ipcdetail::file_wrapper, 16ul, true, false>::priv_open_or_create<boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > >(boost::interprocess::ipcdetail::create_enum_t, char const* const&, unsigned long, boost::interprocess::mode_t, void const*, boost::interprocess::permissions const&, boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> >) boost-1.67.0/include/boost/interprocess/detail/managed_open_or_create_impl.hpp:340:14
#3 0xbaf6133 in boost::interprocess::ipcdetail::managed_open_or_create_impl<boost::interprocess::ipcdetail::file_wrapper, 16ul, true, false>::managed_open_or_create_impl<boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > >(boost::interprocess::open_only_t, char const* const&, boost::interprocess::mode_t, void const*, boost::interprocess::ipcdetail::create_open_func<boost::interprocess::ipcdetail::basic_managed_memory_impl<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index, 16ul> > const&) boost-1.67.0/include/boost/interprocess/detail/managed_open_or_create_impl.hpp:201:7
#4 0xbaf3e24 in boost::interprocess::basic_managed_mapped_file<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index>::basic_managed_mapped_file(boost::interprocess::open_only_t, char const*, void const*) boost-1.67.0/include/boost/interprocess/managed_mapped_file.hpp:120:9
If we take a look on
inline file_wrapper::file_wrapper()
: m_handle(file_handle_t(ipcdetail::invalid_file()))
{}
we can see that m_mode
is not initialized.
I am seeing execution failures when any process tries to modify data that it didn't create.
This is with Win10, MSVC-19 (or CLang 9.0), boost 1.70, MS-MPI 2.0
These tests pass easily under linux.
output...
PS C:\Users\smith\source\repos\TestInterprocess\out\build\x64-Debug> mpiexec -n 1 .\TestInterprocess
Hello world from processor , rank 0 out of 1 processors
Rank [ 0 ] Test passes...
Rank [ 0 ] Test passes...
PS C:\Users\smith\source\repos\TestInterprocess\out\build\x64-Debug> mpiexec -n 2 .\TestInterprocess
job aborted:
[ranks] message
[0] terminated
[1] process exited without calling finalize
---- error analysis -----
[1] on PN1933527
.\TestInterprocess ended prematurely and may have crashed. exit code 0xc0000005
---- error analysis -----
PS
// TestInterprocess.cpp : Defines the entry point for the application.
//
#include <boost/interprocess/managed_shared_memory.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <mpi.h>
#include <algorithm>
namespace bi = boost::interprocess;
struct shmem {
std::string name;
bi::managed_shared_memory segment;
shmem(const std::string& n, int id) : name(n + std::to_string(id)), segment(bi::open_or_create, name.c_str(), 65536) { }
~shmem(void) {
bi::shared_memory_object::remove(name.c_str());
}
//Define an STL compatible allocator of that allocates from the managed_shared_memory.
//This allocator will allow placing containers in the segment
template <typename T>
using allocator = boost::interprocess::allocator<T, bi::managed_shared_memory::segment_manager>;
template <typename T>
auto alloc(void) { return allocator<T>(segment.get_segment_manager()); }
template <typename T>
using vector = std::vector<T, allocator<T>>;
};
template <typename T, typename U>
void CHECK_EQUAL(T&& t, U&& u, int rank) {
if (t == u) {
std::cout << "Rank [ " << rank << " ] Test passes...\n";
}
else {
std::cout << "Rank [ " << rank << " ] Test FAILURE\n";
}
}
int main(int argc, char* argv[])
{
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
// HostInitializesSiblingSorts
using MyVector = shmem::vector<int>;
const unsigned nElements = 100;
MyVector* myvector;
//Create a new segment with given name and size
shmem s("HostInitsSiblingSorts", world_size);
if (world_rank == 0) {
//Construct a vector named "MyVector" in shared memory with argument alloc_inst
myvector = s.segment.construct<MyVector>("MyVector")(s.alloc<int>());
for (int i = 0; i < 100; ++i) //Insert data in the vector
myvector->push_back(i);
MPI_Barrier(MPI_COMM_WORLD); // Init done
MPI_Barrier(MPI_COMM_WORLD); // Sort done
if (world_size == 1) {
CHECK_EQUAL(100, myvector->size(), world_rank);
CHECK_EQUAL(141, myvector->capacity(), world_rank);
// Finalize the MPI environment.
MPI_Finalize();
return 0;
}
}
else { //Sibling process
MPI_Barrier(MPI_COMM_WORLD); // Init done
//Find the vector using the c-string name
myvector = s.segment.find<MyVector>("MyVector").first;
if (world_rank == 1) {
std::sort(myvector->rbegin(), myvector->rend());
//std::reverse(myvector->begin(), myvector->end());
}
MPI_Barrier(MPI_COMM_WORLD); // Sort done
}
CHECK_EQUAL(0, myvector->front(), world_rank);
CHECK_EQUAL(99, myvector->back(), world_rank);
CHECK_EQUAL(100, myvector->size(), world_rank);
CHECK_EQUAL(141, myvector->capacity(), world_rank);
// Finalize the MPI environment.
MPI_Finalize();
return 0;
}
Trying to make managed heap memory with a 64-byte alignment causes the assertion shown below the code.
This asserts when align
> 32 in boost 1.66.0 on CentOS7-64/gcc 7.2:
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/managed_heap_memory.hpp>
using namespace ::std;
using namespace boost::interprocess;
int main(int, char *argv[])
{
constexpr const static size_t align = 64;
typedef basic_managed_heap_memory<
char,
rbtree_best_fit<mutex_family, offset_ptr<void, long, unsigned long, align>, align>,
iset_index
> synchronized_managed_heap_t;
synchronized_managed_heap_t mem(10000); // asserts when align > 32
return 0;
}
boost/interprocess/mem_algo/rbtree_best_fit.hpp:410: void boost::interprocess::rbtree_best_fit<MutexFamily,
VoidMutex, MemAlignment>::priv_add_segment(void*, boost::interprocess::rbtree_best_fit<MutexFamily, VoidMutex, MemAlignment>::size_type)
[with MutexFamily = boost::interprocess::mutex_family; VoidPointer = boost::interprocess::offset_ptr<void, long int, long unsigned int, 64>;
long unsigned int MemAlignment = 64; boost::interprocess::rbtree_best_fit<MutexFamily, VoidMutex, MemAlignment>::size_type = long unsigned int]:
Assertion `priv_end_block() == end_block' failed.
I've set up a Boost IPC shared memory for 32/64bits communication as per comment from Boost header so offset_ptr<SharedType, int32_t, uint64_t, sizeof(std::uint64_t)>
along with rbtree_best_fit's MemoryAlignment sizeof(std::uint64_t)
Boost 1.68
In x86 VS 15.8.8 with /O2 + /Ob2 + /Oi + /Ot + /Oy
and BOOST_INTERPROCESS_DISABLE_FORCEINLINE
The rbtree_algorithms will crash trying to rebalance after erasure. But if I disable the optimisation /Od
, everything will be fine.
This is my example program:
template<typename SharedType>
using OffsetPtr = boost::interprocess::offset_ptr<SharedType, int32_t, uint64_t, sizeof(std::uint64_t)>;
using ManagedWindowsSharedMemory =
boost::interprocess::basic_managed_windows_shared_memory<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, OffsetPtr<void>, sizeof(std::uint64_t)>,
boost::interprocess::iset_index
>;
using ShMemSegmentManager = ManagedWindowsSharedMemory::segment_manager;
using shmMultiMapAllocator = boost::interprocess::allocator<std::pair<unsigned int const, unsigned int>, ShMemSegmentManager>;
using shmMultiMap = boost::unordered_multimap<unsigned int, unsigned int, boost::hash<unsigned int>, std::equal_to<unsigned int>, shmMultiMapAllocator>;
// Win32: /O2 + /Ob2 + /Oi + /Ot + /Oy + BOOST_INTERPROCESS_DISABLE_FORCEINLINE
// crash at rbtree_algorithms::rebalance_after_erasure_restore_invariants
// const node_ptr x_parent_left(NodeTraits::get_left(x_parent));
// 0xC0000005: Access violation reading location 0x00000008.
int main(int argc, char **argv)
{
auto managedShMem = new ManagedWindowsSharedMemory(boost::interprocess::create_only, "shmName", 2*1024*1024, 0);
auto mSpecimenToFileMap = managedShMem->find_or_construct<shmMultiMap>("specimenToFileMap")
(3, boost::hash<unsigned int>(), std::equal_to<unsigned int>(), shmMultiMapAllocator(managedShMem->get_segment_manager()));
for (int i = 0; i < 5000; ++i)
{
mSpecimenToFileMap->insert(std::make_pair<unsigned int, unsigned int>(std::move(unsigned int(i/10)), std::move(unsigned int(i))));
}
mSpecimenToFileMap->clear();
system("pause");
return 0;
}
In x64 without BOOST_INTERPROCESS_DISABLE_FORCEINLINE
, I do not have any issue.
In x86, if I use simple_seq_fit
instead of rbtree_best_fit
, it will not crash with the optimisation on.
Ther is a race on bit-field (https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces#race-on-bit-field).
If we take a look on boost::interprocess::rbtree_best_fit::SizeHolder
:
struct SizeHolder
{
//!This block's memory size (including block_ctrl
//!header) in Alignment units
size_type m_prev_size : sizeof(size_type)*CHAR_BIT;
size_type m_size : sizeof(size_type)*CHAR_BIT - 2;
size_type m_prev_allocated : 1;
size_type m_allocated : 1;
};
non-synchronized access to m_prev_size
and m_size
is a race.
From what I understand from reading source, it is allowed to write UsableByPreviousChunk
bytes past allocated block, or to m_prev_size
of next block. But during allocation reads and writes to m_size
are performed.
To whom it may concern,
I'm currently implementing a system that takes advantage of this awesome library. Implementing shared objects has proven to be decently simple. I'm really enjoying it. However, I'd like to implement an object that can be stored in both shared memory and traditional memory by simply providing an optional allocator as the final param in the constructor.
The part that's proven difficult is compatibility of different allocator types with the interprocess allocator. In other words, I can pass the interprocess allocator as a param and things work well (object is allocated in shared memory). However, I can't pass a different allocator type in its place to use traditional object allocation when the object should be stored elsewhere. This could certainly be the result of inexperience with allocators in C++.
Do you know of a way to achieve this goal that provides simple objects that can be maintained in one class? Up to this point I basically create two objects that are logically identical; one that's allocated in shared memory and one that's not.
Thank you very much for your time and help and for the excellent interprocess library!
Warmest regards,
Hayden McParlane
Hello,
I try to compile one of my project after upgrading to v16.3.4 of VS2019.
Context :
I get these errors :
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\interprocess\detail\win32_api.hpp(925,51): error C2116: 'CreateSemaphoreA': function parameter lists do not match between declarations
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\winapi\semaphore.hpp(25): message : see declaration of 'CreateSemaphoreA'
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\interprocess\detail\win32_api.hpp(925,51): error C2733: 'CreateSemaphoreA': you cannot overload a function with 'C' linkage
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\winapi\semaphore.hpp(25,1): message : see declaration of 'CreateSemaphoreA'
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\interprocess\detail\win32_api.hpp(932,49): error C2116: 'GetSystemInfo': function parameter lists do not match between declarations
1>...\vcpkg_VS2019\installed\x64-windows\include\boost\winapi\system.hpp(31): message : see declaration of 'GetSystemInfo'
1>D:\Commun\Codes\vcpkg_VS2019\installed\x64-windows\include\boost\interprocess\detail\win32_api.hpp(932,49): error C2733: 'GetSystemInfo': you cannot overload a function with 'C' linkage
Is this a known problem ?
I want to only include necessary modules in my project, I'm using git submodules, seems like boost.IPC have more dependency than just Boost.Core
What modules do I need to build and use IPC module?
This simple program:
#include <boost/interprocess/sync/file_lock.hpp>
int main() {
return 0;
}
cross-compiled from linux to Windows 64 bits with mingw-w64 + g++ 8.2.0 with the following command:
x86_64-w64-mingw32-g++-8.2.0 -o interprocess.o -c -O2 -DNDEBUG -Wall -Wextra -std=c++14 -I/softs/win64-mingw-8.2.0/release/boost/include interprocess.cpp
gives the following warnings:
In file included from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/errors.hpp:41,
from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/exceptions.hpp:24,
from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/sync/file_lock.hpp:24,
from interprocess.cpp:1:
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::get_system_time_of_day_information(boost::interprocess::winapi::system_timeofday_information&)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:1676:58: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtQuerySystemInformation_t' {aka 'long int (*)(int, void*, long unsigned int, long unsigned int*)'} [-Wcast-function-type]
dll_func::get(dll_func::NtQuerySystemInformation);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::unlink_file(const char*)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:1892:78: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtSetInformationFile_t' {aka 'long int (*)(void*, boost::interprocess::winapi::io_status_block_t*, void*, long unsigned int, int)'} [-Wcast-function-type]
(NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:1894:94: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtQueryObject_t' {aka 'long int (*)(void*, boost::interprocess::winapi::object_information_class, void*, long unsigned int, long unsigned int*)'} [-Wcast-function-type]
NtQueryObject_t pNtQueryObject = (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:1966:85: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtOpenFile_t' {aka 'long int (*)(void*, long unsigned int, boost::interprocess::winapi::object_attributes_t*, boost::interprocess::winapi::io_status_block_t*, long unsigned int, long unsigned int)'} [-Wcast-function-type]
NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:1967:73: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtClose_t' {aka 'long int (*)(void*)'} [-Wcast-function-type]
NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::get_file_mapping_size(void*, long long int&)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:2413:63: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtQuerySection_t' {aka 'long int (*)(void*, boost::interprocess::winapi::section_information_class, boost::interprocess::winapi::interprocess_section_basic_information*, long unsigned int, long unsigned int*)'} [-Wcast-function-type]
(NtQuerySection_t)dll_func::get(dll_func::NtQuerySection);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::get_semaphore_info(void*, long int&, long int&)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:2426:86: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtQuerySemaphore_t' {aka 'long int (*)(void*, unsigned int, boost::interprocess::winapi::interprocess_semaphore_basic_information*, unsigned int, unsigned int*)'} [-Wcast-function-type]
(winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::query_timer_resolution(long unsigned int*, long unsigned int*, long unsigned int*)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:2437:98: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::NtQueryTimerResolution_t' {aka 'long int (*)(long unsigned int*, long unsigned int*, long unsigned int*)'} [-Wcast-function-type]
(winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::query_performance_counter(long long int*)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:2444:57: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::QueryPerformanceCounter_t' {aka 'int (*)(long long int*)'} [-Wcast-function-type]
dll_func::get(dll_func::QueryPerformanceCounter);
^
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp: In function 'bool boost::interprocess::winapi::query_performance_frequency(long long int*)':
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:2451:59: warning: cast between incompatible function types from 'boost::interprocess::winapi::farproc_t' {aka 'long long int (*)()'} to 'boost::interprocess::winapi::QueryPerformanceFrequency_t' {aka 'int (*)(long long int*)'} [-Wcast-function-type]
dll_func::get(dll_func::QueryPerformanceFrequency);
^
You can observe failures in interprocess flat_tree_test test on regression matrix on msvc runners. It started failing after boostorg/container@6ce2b2d (when I git checkout 6ce2b2d0f896d5c4d2c1d071a2908e1aea0311f5^1
the test pass and with git checkout 6ce2b2d0f896d5c4d2c1d071a2908e1aea0311f5
it fails). I am not sure if a bug in interprocess or in container, but the fail happens only on 64bit (.\b2 address-model=64 toolset=msvc-14.1 libs/interprocess/test//flat_tree_test
) making me to think it is most likely in interprocess.
void yield()
{
//Lazy initialization of limits
if( !m_k){
this->init_limits();
}
//Nop tries
if( m_k < (nop_pause_limit >> 2) ){
}
//Pause tries if the processor supports it
#if defined(BOOST_INTERPROCESS_SMT_PAUSE)
else if( m_k < nop_pause_limit ){
BOOST_INTERPROCESS_SMT_PAUSE
}
#endif
//Yield/Sleep strategy
else{
//Lazy initialization of tick information
if(m_k == nop_pause_limit){
this->init_tick_info();
}
else if( this->yield_or_sleep() ){
ipcdetail::thread_yield();
}
else{
ipcdetail::thread_sleep_tick();
}
}
++m_k;
}
boost::interprocess::sync::file_lock currently does not support unicode paths on windows.
This patch adds support for them on windows:
For now it just says whether it succeeded or not.
Platform: Win32, 64-bit (Windows 10)
Compiler: Visual C++ 2015 (14.0.25431.01 Update 3)
Boost Version: 1.70
The following test code:
boost::interprocess::file_lock flock(path);
{
boost::interprocess::scoped_lock<boost::interprocess::file_lock> held_lock(flock);
{
std::ofstream output(path);
output << "Hello" << std::endl;
output.flush();
if (output.bad()) {
std::cout << "Failed to write to output" << std::endl;
}
}
std::cout << "Stream complete" << std::endl;
}
std::cout << "File unlocked" << std::endl;
fails to write anything to path
, and reports that output.bad()
is true.
From inspecting the source, on Windows file_lock
uses LockFileEx
. According to the MSDN documentation, LockFileEx
prevents any other handle from accessing the file, even in the same process; specifically:
If the locking process opens the file a second time, it cannot access the specified region through this second handle until it unlocks the region.
This is actually a bit misleading; opening the file before acquiring the lock also has the same issue.
Testing with similar code using the Win32 API directly results in the same issue; all subsequent I/O must use the same handle used to lock the file.
Note that while using a dummy file name would avoid the I/O issue, this has two side effects:
As such, either boost must use a locking mechanism that does not use LockFileEx
(perhaps named_mutex
?), or some (generic) way of obtaining a stream from the lock is required. Unfortunately the latter seems to be a breaking change in file_lock
behaviour.
I get these warnings from https://github.com/boostorg/interprocess/blob/develop/include/boost/interprocess/detail/win32_api.hpp#L145 (also L153, L178 and L180).
This seems to be similar to this issue.
boost_1_69_0/boost/interprocess/detail/os_file_functions.hpp:546:32: Possible misuse of comma operator here
also line 581
There are a number of compilation of Boost.Interprocess on Cygwin. On 32-bit Cygwin the errors are:
./boost/interprocess/detail/os_thread_functions.hpp: In function �int boost::interprocess::ipcdetail::thread_create(boost::interprocess::ipcdetail::OS_thread_t*, unsigned int (__attribute__((__stdcall__)) *)(void*), void*)’:
./boost/interprocess/detail/os_thread_functions.hpp:524:21: error: �_beginthreadex’ was not declared in this scope
void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
^~~~~~~~~~~~~~
_beginthreadex
is not a Windows API function, it is specific to MSVC RTL, which is not used on Cygwin. You can use pthreads on this platform.
In addition to that, 64-bit Cygwin is a LP64 platform, meaning that long
is a 64-bit integer on that platform. This means that a great deal of Windows SDK emulation layer in Boost.Interprocess is not ABI-compatible with that platform. This results in errors like these:
./boost/interprocess/detail/win32_api.hpp: In function ‘int boost::interprocess::winapi::release_semaphore(void*, long int, long int*)’:
./boost/interprocess/detail/win32_api.hpp:1358:61: error: cannot convert ‘long int*’ to ‘LPLONG {aka int*}’ for argument ‘3’ to ‘WINBOOL ReleaseSemaphore(HANDLE, LONG, LPLONG)’
{ return ReleaseSemaphore(handle, release_count, prev_count); }
^
./boost/interprocess/detail/win32_api.hpp: In function ‘bool boost::interprocess::winapi::virtual_protect(void*, std::size_t, long unsigned int, long unsigned int&)’:
./boost/interprocess/detail/win32_api.hpp:1428:81: error: cannot convert ‘long unsigned int*’ to ‘PDWORD {aka unsigned int*}’ for argument ‘4’ to ‘WINBOOL VirtualProtect(LPVOID, SIZE_T, DWORD, PDWORD)’
{ return 0 != VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); }
^
./boost/interprocess/detail/win32_api.hpp: In function ‘bool boost::interprocess::winapi::write_file(void*, const void*, long unsigned int, long unsigned int*, boost::interprocess::winapi::interprocess_overlapped*)’:
./boost/interprocess/detail/win32_api.hpp:1464:80: error: cannot convert ‘long unsigned int*’ to ‘LPDWORD {aka unsigned int*}’ for argument ‘4’ to ‘WINBOOL WriteFile(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED)’
{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); }
^
./boost/interprocess/detail/win32_api.hpp: In function ‘bool boost::interprocess::winapi::read_file(void*, void*, long unsigned int, long unsigned int*, boost::interprocess::winapi::interprocess_overlapped*)’:
./boost/interprocess/detail/win32_api.hpp:1467:75: error: cannot convert ‘long unsigned int*’ to ‘LPDWORD {aka unsigned int*}’ for argument ‘4’ to ‘WINBOOL ReadFile(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)’
{ return 0 != ReadFile(hnd, buffer, bytes_to_read, bytes_read, overlapped); }
^
./boost/interprocess/detail/win32_api.hpp: In function ‘long int boost::interprocess::winapi::reg_query_value_ex(boost::interprocess::winapi::hkey, const char*, long unsigned int*, long unsigned int*, unsigned char*, long unsigned int*)’:
./boost/interprocess/detail/win32_api.hpp:1507:83: error: cannot convert ‘long unsigned int*’ to ‘LPDWORD {aka unsigned int*}’ for argument ‘3’ to ‘LONG RegQueryValueExA(HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)’
{ return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
^
./boost/interprocess/detail/win32_api.hpp: In function ‘bool boost::interprocess::winapi::get_last_bootup_time(std::string&)’:
./boost/interprocess/detail/win32_api.hpp:2341:40: error: cannot convert ‘long unsigned int*’ to ‘DWORD* {aka unsigned int*}’ for argument ‘6’ to ‘WINBOOL ReadEventLogA(HANDLE, DWORD, DWORD, LPVOID, DWORD, DWORD*, DWORD*)’
&dwMinimumBytesToRead)) {
^
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::interlocked_increment(volatile long int*)’:
./boost/interprocess/detail/win32_api.hpp:1473:62: error: no matching function for call to �_InterlockedIncrement(long int*)’
{ return BOOST_INTERLOCKED_INCREMENT(const_cast<long*>(addr)); }
^
In file included from /usr/include/w32api/windows.h:70:0,
from ./boost/winapi/basic_types.hpp:19,
from ./boost/winapi/error_codes.hpp:11,
from ./boost/system/detail/system_category_win32.hpp:12,
from ./boost/system/error_code.hpp:905,
from ./boost/log/exceptions.hpp:23,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:42:
/usr/include/w32api/winbase.h:2937:29: note: candidate: long unsigned int _InterlockedIncrement(volatile long unsigned int*) <near match>
FORCEINLINE unsigned long InterlockedIncrement (unsigned long volatile *Addend) {
^
/usr/include/w32api/winbase.h:2937:29: note: conversion of argument 1 would be ill-formed:
In file included from ./boost/interprocess/errors.hpp:41:0,
from ./boost/interprocess/exceptions.hpp:24,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:49:
./boost/interprocess/detail/win32_api.hpp:1473:39: error: invalid conversion from �long int*’ to �volatile long unsigned int*’ [-fpermissive]
{ return BOOST_INTERLOCKED_INCREMENT(const_cast<long*>(addr)); }
^~~~~~~~~~~~~~~~~~~~~~~
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::interlocked_decrement(volatile long int*)’:
./boost/interprocess/detail/win32_api.hpp:1476:62: error: no matching function for call to �_InterlockedDecrement(long int*)’
{ return BOOST_INTERLOCKED_DECREMENT(const_cast<long*>(addr)); }
^
In file included from /usr/include/w32api/windows.h:70:0,
from ./boost/winapi/basic_types.hpp:19,
from ./boost/winapi/error_codes.hpp:11,
from ./boost/system/detail/system_category_win32.hpp:12,
from ./boost/system/error_code.hpp:905,
from ./boost/log/exceptions.hpp:23,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:42:
/usr/include/w32api/winbase.h:2955:29: note: candidate: long unsigned int _InterlockedDecrement(volatile long unsigned int*) <near match>
FORCEINLINE unsigned long InterlockedDecrement (unsigned long volatile *Addend) {
^
/usr/include/w32api/winbase.h:2955:29: note: conversion of argument 1 would be ill-formed:
In file included from ./boost/interprocess/errors.hpp:41:0,
from ./boost/interprocess/exceptions.hpp:24,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:49:
./boost/interprocess/detail/win32_api.hpp:1476:39: error: invalid conversion from �long int*’ to �volatile long unsigned int*’ [-fpermissive]
{ return BOOST_INTERLOCKED_DECREMENT(const_cast<long*>(addr)); }
^~~~~~~~~~~~~~~~~~~~~~~
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::interlocked_compare_exchange(volatile long int*, long int, long int)’:
./boost/interprocess/detail/win32_api.hpp:1479:81: error: no matching function for call to �_InterlockedCompareExchange(long int*, long int&, long int&)’
{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(const_cast<long*>(addr), val1, val2); }
^
In file included from /usr/include/w32api/windows.h:70:0,
from ./boost/winapi/basic_types.hpp:19,
from ./boost/winapi/error_codes.hpp:11,
from ./boost/system/detail/system_category_win32.hpp:12,
from ./boost/system/error_code.hpp:905,
from ./boost/log/exceptions.hpp:23,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:42:
/usr/include/w32api/winbase.h:3025:29: note: candidate: long unsigned int _InterlockedCompareExchange(volatile long unsigned int*, long unsigned int, long unsigned int) <near match>
FORCEINLINE unsigned long InterlockedCompareExchange (unsigned long volatile *Destination, unsigned long Exchange, unsigned long Comperand) {
^
/usr/include/w32api/winbase.h:3025:29: note: conversion of argument 1 would be ill-formed:
In file included from ./boost/interprocess/errors.hpp:41:0,
from ./boost/interprocess/exceptions.hpp:24,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:49:
./boost/interprocess/detail/win32_api.hpp:1479:46: error: invalid conversion from �long int*’ to �volatile long unsigned int*’ [-fpermissive]
{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(const_cast<long*>(addr), val1, val2); }
^~~~~~~~~~~~~~~~~~~~~~~
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::interlocked_exchange_add(volatile long int*, long int)’:
./boost/interprocess/detail/win32_api.hpp:1482:74: error: no matching function for call to �_InterlockedExchangeAdd(long int*, long int&)’
{ return BOOST_INTERLOCKED_EXCHANGE_ADD(const_cast<long*>(addend), value); }
^
In file included from /usr/include/w32api/windows.h:70:0,
from ./boost/winapi/basic_types.hpp:19,
from ./boost/winapi/error_codes.hpp:11,
from ./boost/system/detail/system_category_win32.hpp:12,
from ./boost/system/error_code.hpp:905,
from ./boost/log/exceptions.hpp:23,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:42:
/usr/include/w32api/winbase.h:2995:29: note: candidate: long unsigned int _InterlockedExchangeAdd(volatile long unsigned int*, long unsigned int) <near match>
FORCEINLINE unsigned long InterlockedExchangeAdd (unsigned long volatile *Addend, unsigned long Value) {
^
/usr/include/w32api/winbase.h:2995:29: note: conversion of argument 1 would be ill-formed:
In file included from ./boost/interprocess/errors.hpp:41:0,
from ./boost/interprocess/exceptions.hpp:24,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:49:
./boost/interprocess/detail/win32_api.hpp:1482:42: error: invalid conversion from �long int*’ to �volatile long unsigned int*’ [-fpermissive]
{ return BOOST_INTERLOCKED_EXCHANGE_ADD(const_cast<long*>(addend), value); }
^~~~~~~~~~~~~~~~~~~~~~~~~
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::interlocked_exchange(volatile long int*, long int)’:
./boost/interprocess/detail/win32_api.hpp:1485:70: error: no matching function for call to �_InterlockedExchange(long int*, long int&)’
{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
^
In file included from /usr/include/w32api/windows.h:70:0,
from ./boost/winapi/basic_types.hpp:19,
from ./boost/winapi/error_codes.hpp:11,
from ./boost/system/detail/system_category_win32.hpp:12,
from ./boost/system/error_code.hpp:905,
from ./boost/log/exceptions.hpp:23,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:42:
/usr/include/w32api/winbase.h:2973:29: note: candidate: long unsigned int _InterlockedExchange(volatile long unsigned int*, long unsigned int) <near match>
FORCEINLINE unsigned long InterlockedExchange (unsigned long volatile *Target, unsigned long Value) {
^
/usr/include/w32api/winbase.h:2973:29: note: conversion of argument 1 would be ill-formed:
In file included from ./boost/interprocess/errors.hpp:41:0,
from ./boost/interprocess/exceptions.hpp:24,
from libs/log/src/posix/ipc_reliable_message_queue.cpp:49:
./boost/interprocess/detail/win32_api.hpp:1485:38: error: invalid conversion from �long int*’ to �volatile long unsigned int*’ [-fpermissive]
{ return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); }
^~~~~~~~~~~~~~~~~~~~~~~~~
./boost/interprocess/detail/win32_api.hpp: In function �long int boost::interprocess::winapi::reg_query_value_ex(boost::interprocess::winapi::hkey, const char*, long unsigned int*, long unsigned int*, unsigned char*, long unsigned int*)’:
./boost/interprocess/detail/win32_api.hpp:1507:83: error: cannot convert �long unsigned int*’ to �LPDWORD {aka unsigned int*}’ for argument �3’ to �LONG RegQueryValueExA(HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)’
{ return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); }
^
./boost/interprocess/detail/win32_api.hpp: In function �bool boost::interprocess::winapi::get_last_bootup_time(std::string&)’:
./boost/interprocess/detail/win32_api.hpp:2341:40: error: cannot convert �long unsigned int*’ to �DWORD* {aka unsigned int*}’ for argument �6’ to �WINBOOL ReadEventLogA(HANDLE, DWORD, DWORD, LPVOID, DWORD, DWORD*, DWORD*)’
&dwMinimumBytesToRead)) {
^
My advice would be to port the library to Boost.WinAPI, which already has workarounds in place for Cygwin64.
In file boost\interprocess\errors.hpp
the function fill_system_message()
invokes winapi::format_message()
but then doesn't check its return value and calls string::operator+=
with lpMsgBuf=nullptr
. Obviously it leads to access violation.
boost_1_69_0/boost/interprocess/streams/bufferstream.hpp:241:25: Implicit conversion loses integer precision: 'boost::interprocess::basic_bufferbuf<char, std::__1::char_traits >::off_type' (aka 'long long') to 'int'
I've been using boost::interprocess::message_queue_t
to implement communication between two processes. I need to have it resilient to process crashes, so I have defined: BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
It helped in most cases, but occasionally message_queue::timed_push
was still hanging with a stack trace leading to:
MyApp.dll!boost::interprocess::ipcdetail::try_based_lock<boost::interprocess::ipcdetail::spin_mutex>(boost::interprocess::ipcdetail::spin_mutex & m) Line 71 C++
MyApp.dll!boost::interprocess::ipcdetail::spin_mutex::lock() Line 67 C++
MyApp.dll!boost::interprocess::ipcdetail::spin_condition::notify(unsigned int command) Line 150 C++
MyApp.dll!boost::interprocess::ipcdetail::spin_condition::notify_one() Line 133 C++
MyApp.dll!boost::interprocess::interprocess_condition::notify_one() Line 93 C++
MyApp.dll!boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0> >::do_send(boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0> >::block_t block, const void * buffer, unsigned __int64 buffer_size, unsigned int priority, const boost::posix_time::ptime & abs_time) Line 817 C++
MyApp.dll!boost::interprocess::message_queue_t<boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0> >::timed_send(const void * buffer, unsigned __int64 buffer_size, unsigned int priority, const boost::posix_time::ptime & abs_time) Line 717 C++
I've investigated and tried to pinpoint where the problem is. I've come up with minimal code to have the problem reproduced stable:
Producer:
void spin_deadlock_test()
{
using namespace boost::interprocess;
named_condition::remove("my_named_condition");
named_mutex::remove("my_named_mutex");
named_condition cond{ create_only, "my_named_condition" };
named_mutex mtx{ create_only, "my_named_mutex" };
try
{
while (true)
{
cond.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "P: Still alive!" << std::endl;
}
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
std::cout << "Press any key to continue" << std::endl;
getchar();
}
Consumer:
void spin_deadlock_test()
{
using namespace boost::interprocess;
named_condition cond{ open_only, "my_named_condition" };
named_mutex mtx{ open_only, "my_named_mutex" };
try
{
while (true)
{
scoped_lock<named_mutex> lock(mtx);
cond.wait(lock);
std::cout << "C: Still alive!" << std::endl;
}
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
std::cout << "Press any key to continue" << std::endl;
getchar();
}
Producer output (started first):
P: Still alive!
P: Still alive!
P: Still alive!
<consumer is started here>
P: Still alive!
P: Still alive!
P: Still alive!
<consumer app is closed here>
P: Still alive!
<no more output>
Expected: is to have exception thrown or for the app to continue working
Bootup time is needed in boost::interprocess for creating a unique shared directory which remains identical for all processes started since last reboots, but different between reboots. Currently people have choice to get the bootup time by define following macros:
1. BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME (not recommended due to instability with time synchronization and hibernation and unusable in practice)
2. BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED (It's a default method, if none of the macro is defined, fetches bootup time from system event log, Id 6005)
3. BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED (fetches bootup time from registry setting, path : HKEY_LOCAL_MACHINE→ SYSTEM → CurrentControlSet → Control → Session Manager → Memory Management → PrefetchParameters → BootID)
The problem with 2 & 3 is that if the Windows system event log with ID 6005 and registry key BootID gets deleted then the application throws runtime exception. We have already been notified of these issues by different users of our application and hence the idea is to propose a new method which can be used on Windows OS that supports of:
* Minimum supported client -> Windows Vista
* Minimum supported server -> Windows server 2008
Since this issue is in existence from long time and for those who are using newer Windows OS, provide them the flexibility to use GetTickCount64 for calculating bootup time by define a new preprocessor macro BOOST_INTERPROCESS_BOOTSTAMP_IS_GETTICKCOUNT64_BASED
in boost/interprocess/detail/win32_api.hpp
I have added a patch for having a better view of suggested change. Please provide your feedback if the change can be pulled into Boost. If so I can submit a PR for this.
tried on macOS
I saw Issue #96 (Getting bootup time on Windows is not stable) . That proposal may be useful. There have been discussions on this stability theme over many years.
I work with a premium desktop product (Autodesk Revit) . It employs boost interprocess in production. Long ago, we chose the boot time stamp strategy = BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME and we have been pretty happy with it.
Yes, in the wild, mucking with the system time, or other randomness, invalidates it . In that case, our application refuses to start up. To us, systems administered with professional-level IT rarely exhibit that kind of problem. So that's good.
New problem, though. We see it with a newly minted Windows 10 VM image. I won't go into a painful level of detail unless asked. When we start application, and get the last bootup time, via boost interprocess API, sometimes answer is off by exactly one hour! Chaos ensues. It has now been noticed that on these VMs, the system current time zone synchronously fluctuates, but in a complementary way. This suggests a revised calculation may eliminate fluctuation problem. (Currently integrated with boost 1.68.0).
Any advice or news on this?
I believe i have also ran into the issue described in this stack overflow post.
Is the official stance to just use fixed addess mapping or can this issue be addressed?
In our scenario, there are two processes(one side 32-bit and other one 64-bit) communicate with each other over shared memory.
Boost Version : 1.70.0
Compiler Version : gcc 7.4.0
Here is the implementation code for 64-bit side as like that:
#define QUEUE_CAPACITY 5
namespace bi = boost::interprocess;
using adn_linux_ptr_t = bi::offset_ptr<void, std::int32_t, std::uint64_t, sizeof(std::uint64_t)>;
using adn_linux_external_buf_t = bi::basic_managed_external_buffer<char, bi::rbtree_best_fit<bi::null_mutex_family, adn_linux_ptr_t, sizeof(std::uintptr_t)>, bi::iset_index>;
namespace shm
{
using handle = adn_linux_external_buf_t::handle_t;
using ring_buffer = boost::lockfree::spsc_queue<handle, boost::lockfree::capacity<QUEUE_CAPACITY>>;
}
int main(int argc, char argv[])
{
adn_linux_external_buf_t segment(bi::open_only, shared_mem_addr, SEGMENT_SIZE);
std::cout << "Segment is created " << std::hex << addressof(segment) << std::endl;
auto seg_ptr = segment.get_segment_manager();
if(nullptr == seg_ptr)
{
std::cout << "Segment manager failed" << std::endl;
return 0;
}
size_t free_size = segment.get_free_memory();
if(0 == free_size)
{
std::cout << "No free memory available!" << std::endl;
return 0;
}
if(!segment.check_sanity())
{
std::cout << "Check sanity failed!" << std::endl;
return 0;
}
std::cout << "Free available memory size: " << free_size << std::endl;
auto f_ping_queue = segment.find<shm::ring_buffer>("ping_queue");
auto f_pong_queue = segment.find<shm::ring_buffer>("pong_queue");
shm::ring_buffer *ping_queue = f_ping_queue.first;
shm::ring_buffer *pong_queue = f_pong_queue.first;
if(ping_queue == nullptr || pong_queue == nullptr)
{
std::cout << "One or more queue could not be created!" << std::endl;
return 0;
}
}
In 32-bit side, implementation can be represented like that:
namespace bi = boost::interprocess;
using adn_linux_ptr_t = bi::offset_ptr<void, std::int32_t, std::uint64_t, sizeof(std::uint64_t)>;
using adn_linux_external_buf_t = bi::basic_managed_external_buffer<char, bi::rbtree_best_fit<bi::null_mutex_family, adn_linux_ptr_t, sizeof(boost::uint64_t)>, bi::iset_index>;
namespace shm
{
using handle = adn_linux_external_buf_t::handle_t;
using ring_buffer = boost::lockfree::spsc_queue<handle, boost::lockfree::capacity<QUEUE_CAPACITY> >;
}
int main(int argc, char *argv[])
{
adn_linux_external_buf_t segment(bi::create_only, shared_mem_addr, SEGMENT_SIZE);
size_t free_size = segment.get_free_memory();
if(0 == free_size)
{
std::cout << "No memory available!\n";
return;
}
if(!segment.check_sanity())
{
std::cout << "Check sanity failed!\n";
return;
}
std::cout << "Free memory size is : " << free_size << std::endl;
shm::ring_buffer *f_ping_queue = segment.construct<shm::ring_buffer>("ping_queue")();
shm::ring_buffer *f_pong_queue = segment.construct<shm::ring_buffer>("pong_queue")();
if(f_ping_queue == 0 || f_pong_queue == 0)
{
std::cout << "Queues could not be created\n";
return;
}
std::cout << "Queues are available\n";
adn_linux_external_buf_t::handle_t handle = 0;
return 0;
}
For communication to each other, we just adjust offset_ptr template on both side but we are getting assertion from 64-bit process in file segment_manager.hpp:861 as you can see below:
consumer: ./boost/interprocess/segment_manager.hpp:861: void* boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::priv_generic_find(const CharT*, IndexType<boost::interprocess::ipcdetail::index_config<CharT, MemoryAlgorithm> >&, boost::interprocess::ipcdetail::in_place_interface&, boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::size_type&, boost::interprocess::ipcdetail::true_, bool) [with CharT = char; CharType = char; MemoryAlgorithm = boost::interprocess::rbtree_best_fit<boost::interprocess::null_mutex_family, boost::interprocess::offset_ptr<void, int, long unsigned int, 8>, 8>; IndexType = boost::interprocess::iset_index; boost::interprocess::segment_manager<CharType, MemoryAlgorithm, IndexType>::size_type = unsigned int; boost::interprocess::ipcdetail::true_ = boost::interprocess::ipcdetail::bool_<true>]: Assertion (ctrl_data->m_value_bytes % table.size) == 0' failed.
PS: shared_mem_addr is somewhere which is mmap from the system as a shared memory where both processes can have access on it.
So, as far as I can see from Boost issue tracker, offset_ptr should be re-defined for our purpose as above. However, problem is still occurred.
In the following code, located in boost/interprocess/detail/win32_api.hpp, ::realloc may move the referenced memory block to a new location. If this happens, the memory is lost.
class c_heap_deleter
{
public:
explicit c_heap_deleter(std::size_t size)
: m_buf(::malloc(size))
{}
~c_heap_deleter()
{
if(m_buf) ::free(m_buf);
}
void realloc_mem(std::size_t num_bytes)
{
void *buf = ::realloc(m_buf, num_bytes); // problem is here. If the memory is moved, the buffer is lost.
if(!buf){
::free(m_buf);
m_buf = 0;
}
}
void *get() const
{ return m_buf; }
private:
void *m_buf;
;
I would suggest re-writing the method like so:
void realloc_mem(std::size_t num_bytes)
{
void *oldBuf = m_buf;
m_buf = ::realloc(m_buf, num_bytes);
if (!m_buf){
free(oldBuf);
}
}
This simple program:
#include <boost/interprocess/sync/file_lock.hpp>
int main() {
return 0;
}
cross-compiled from linux to Windows 64 bits with mingw-w64 + g++ 8.2.0 with the following command:
x86_64-w64-mingw32-g++-8.2.0 -o interprocess.o -c -Wnon-virtual-dtor -std=c++14 -I/softs/win64-mingw-8.2.0/release/boost/include interprocess.cpp
gives the following warnings:
In file included from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/errors.hpp:41,
from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/exceptions.hpp:24,
from /softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/sync/file_lock.hpp:24,
from interprocess.cpp:1:
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:189:8: warning: 'struct boost::interprocess::winapi::IUnknown_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IUnknown_BIPC
^~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:200:8: warning: base class 'struct boost::interprocess::winapi::IUnknown_BIPC' has accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IWbemClassObject_BIPC : public IUnknown_BIPC
^~~~~~~~~~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:200:8: warning: 'struct boost::interprocess::winapi::IWbemClassObject_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:306:8: warning: base class 'struct boost::interprocess::winapi::IUnknown_BIPC' has accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IWbemContext_BIPC : public IUnknown_BIPC
^~~~~~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:306:8: warning: 'struct boost::interprocess::winapi::IWbemContext_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:345:8: warning: base class 'struct boost::interprocess::winapi::IUnknown_BIPC' has accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IEnumWbemClassObject_BIPC : public IUnknown_BIPC
^~~~~~~~~~~~~~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:345:8: warning: 'struct boost::interprocess::winapi::IEnumWbemClassObject_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:369:8: warning: base class 'struct boost::interprocess::winapi::IUnknown_BIPC' has accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IWbemServices_BIPC : public IUnknown_BIPC
^~~~~~~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:369:8: warning: 'struct boost::interprocess::winapi::IWbemServices_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:518:8: warning: base class 'struct boost::interprocess::winapi::IUnknown_BIPC' has accessible non-virtual destructor [-Wnon-virtual-dtor]
struct IWbemLocator_BIPC : public IUnknown_BIPC
^~~~~~~~~~~~~~~~~
/softs/win64-mingw-8.2.0/release/boost/include/boost/interprocess/detail/win32_api.hpp:518:8: warning: 'struct boost::interprocess::winapi::IWbemLocator_BIPC' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
boost 1.70
Windows 7 x64
VS2015
When I try to create mapped_region only with 'offset' argument, the function priv_size_from_mapping_size() returns the wrong size of a tail that causes crash in map_view_of_file_ex () and throw of an exception.
The size is calculated as: size = mapping_size - (offset - page_offset)
The function map_view_of_file_ex() receives address (offset - page_offset) and the size (page_offset + size). Their sum is (size + offset). It is obvious that if the 'page_offset' is not zero, then the sum exceeds 'mapping_size'. It causes access violation in the low-level MapViewOfFile() function.
index 1fb6408..5c58cb6 100644
--- a/mapped_region.hpp
+++ "b/mapped_region.hpp"
@@ -353,7 +353,7 @@ inline void mapped_region::priv_size_from_mapping_size
error_info err(size_error);
throw interprocess_exception(err);
}
- size = static_cast<std::size_t>(mapping_size - (offset - page_offset));
+ size = static_cast<std::size_t>(mapping_size - offset);
}
inline offset_t mapped_region::priv_page_offset_addr_fixup(offset_t offset, const void *&address)
OS: Windows 10 x64
Visual studio 2019 (16.3.1)
Windows SDK: 10.0.18362.0
boost 1.71
Sample program:
`
#define _WIN32_WINNT 0x0601
#include <Windows.h>
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
int main()
{
return 0;
}
`
74 errors during compilation!
result.txt
The documentation of boost::interprocess::file_lock has some cautions on synchronization limitations:
But then gives the guidance:
I then created the following example:
https://wandbox.org/permlink/dO2rRDCHVWBE3pGrhttps://wandbox.org/permlink/3CNfkA3RcMkwbd2v
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/filesystem.hpp>
#include <mutex>
#include <thread>
#include <chrono>
int main()
{
std::ofstream("f.txt");
boost::interprocess::file_lock lock("f.txt");
std::mutex mtx;
const size_t max = 100;
size_t t1Count = 0;
std::thread
t1
(
[&lock,&t1Count,&mtx,max]()
{
while(t1Count < max)
{
//std::lock_guard<std::mutex> mtxLock(mtx);
boost::interprocess::scoped_lock<boost::interprocess::file_lock> guard(lock);
std::cout << "Number 1" << std::endl;
t1Count++;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
);
size_t t2Count = 0;
std::thread
t2
(
[&lock,&t2Count,&mtx,max]()
{
while(t2Count < max)
{
//std::lock_guard<std::mutex> mtxLock(mtx);
boost::interprocess::scoped_lock<boost::interprocess::file_lock> guard(lock);
std::cout << "Number 2" << std::endl;
t2Count++;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
);
t1.join();
t2.join();
return 0;
}
It only works properly if the std::mutex is used in addition to the file_lock. That was originally my thought when I read "It's unspecified if a file_lock synchronizes two threads from the same process.", but it seemed like I was following the guidance "Use the same thread to lock and unlock a file.". If I haven't messed anything up, I would probably update the documentation to say something like:
"If utilitizing the file_lock from multiple threads within the same process, synchronize access to the file_lock with an intraprocess synchronization mechanism such as a mutex."
Otherwise, is it a bug?
Thanks,
Rob
We tried to build and run interprocess test for Boost. It failed to build due to the error C2039, C3083, C2873,C2988 and so on. Could you please help take a look at this? Thanks!
Reproduce steps:
Expected result:
All tests passed
Actual result:
.\boost/interprocess/detail/variadic_templates_tools.hpp(28): error C2039: 'dtl': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(28): error C3083: 'dtl': the symbol to the left of a '::' must be a type
.\boost/interprocess/detail/variadic_templates_tools.hpp(28): error C2039: 'tuple': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(28): error C2873: 'tuple': symbol cannot be used in a using-declaration
.\boost/interprocess/detail/variadic_templates_tools.hpp(29): error C2039: 'dtl': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(29): error C3083: 'dtl': the symbol to the left of a '::' must be a type
.\boost/interprocess/detail/variadic_templates_tools.hpp(29): error C2039: 'build_number_seq': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(29): error C2873: 'build_number_seq': symbol cannot be used in a using-declaration
.\boost/interprocess/detail/variadic_templates_tools.hpp(30): error C2039: 'dtl': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(30): error C3083: 'dtl': the symbol to the left of a '::' must be a type
.\boost/interprocess/detail/variadic_templates_tools.hpp(30): error C2039: 'index_tuple': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(30): error C2873: 'index_tuple': symbol cannot be used in a using-declaration
.\boost/interprocess/detail/variadic_templates_tools.hpp(31): error C2039: 'dtl': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(31): error C3083: 'dtl': the symbol to the left of a '::' must be a type
.\boost/interprocess/detail/variadic_templates_tools.hpp(31): error C2039: 'get': is not a member of 'boost::container'
.\boost/container/detail/variadic_templates_tools.hpp(30): note: see declaration of 'boost::container'
.\boost/interprocess/detail/variadic_templates_tools.hpp(31): error C2873: 'get': symbol cannot be used in a using-declaration
.\boost/interprocess/detail/named_proxy.hpp(53): error C2143: syntax error: missing ';' before '<'
.\boost/interprocess/detail/named_proxy.hpp(102): note: see reference to class template instantiation 'boost::interprocess::ipcdetail::CtorArgN<T,is_iterator,Args...>' being compiled
.\boost/interprocess/detail/named_proxy.hpp(53): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(53): error C2238: unexpected token(s) preceding ';'
.\boost/interprocess/detail/named_proxy.hpp(80): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(80): error C2988: unrecognizable template declaration/definition
.\boost/interprocess/detail/named_proxy.hpp(80): error C2143: syntax error: missing ',' before '<'
.\boost/interprocess/detail/named_proxy.hpp(84): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(84): error C2988: unrecognizable template declaration/definition
.\boost/interprocess/detail/named_proxy.hpp(84): error C2143: syntax error: missing ',' before '<'
.\boost/interprocess/detail/named_proxy.hpp(88): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(88): error C2988: unrecognizable template declaration/definition
.\boost/interprocess/detail/named_proxy.hpp(88): error C2143: syntax error: missing ',' before '<'
.\boost/interprocess/detail/named_proxy.hpp(98): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(98): error C2988: unrecognizable template declaration/definition
.\boost/interprocess/detail/named_proxy.hpp(98): error C2143: syntax error: missing ',' before '<'
.\boost/interprocess/detail/named_proxy.hpp(101): error C2143: syntax error: missing ';' before '<'
.\boost/interprocess/detail/named_proxy.hpp(101): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/detail/named_proxy.hpp(101): error C2238: unexpected token(s) preceding ';'
.\boost/interprocess/offset_ptr.hpp(69): error C3083: 'dtl': the symbol to the left of a '::' must be a type
.\boost/interprocess/offset_ptr.hpp(73): note: see reference to class template instantiation 'boost::interprocess::ipcdetail::offset_ptr_internal<OffsetType,OffsetAlignment>' being compiled
.\boost/interprocess/offset_ptr.hpp(70): error C2143: syntax error: missing ';' before '<'
.\boost/interprocess/offset_ptr.hpp(70): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\boost/interprocess/offset_ptr.hpp(71): error C2334: unexpected token(s) preceding ':'; skipping apparent function body
.\boost/interprocess/offset_ptr.hpp(55): fatal error C1075: '{': no matching token found
clang (macos/linux) is not listed as a tested compiler, but is the level of support known? Any known issues? Thanks for any input.
Hello there,
I'm working on a big project on Windows where two processes A and B exchange data using boost.interprocess. The problem is : when I use notify_all()
, it takes about 15 msec to wake up the waiter (I posted my problem yesterday here: https://stackoverflow.com/questions/47269091/boost-interprocess-notify-performance
I end up writing a small exemple that reproduces my problem here: https://github.com/poukill/boost_notify_latency
Today I tried to use Windows Events instead of the wait()/notify_all() function and I got 0.04ms of latency every time, which is very good. Somehow the implementation of the notify_all()
seems slow on Windows (trapped into context switch ???)
Could you help me on that issue ?
Thanks a lot,
Gwen
The shm_named_condition_any
class' wait
, timed_wait
, notify_one
, and notify_all
functions are implemented using the local instance of internal_condition_members
, m_cond
, instead of using the one in shared memory, this causes named_condition_any
to never send/receive notifications
To reproduce you need an instrumented stdlib (I used clang-7 and libc++-7 from LLVM repo).
==19941==ERROR: AddressSanitizer: container-overflow on address 0x62600000360a at pc 0x00000043496a bp 0x7ffc8aded210 sp 0x7ffc8adec998
READ of size 1291 at 0x62600000360a thread T0
#0 0x434969 in __interceptor_strcmp /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:432:3
#1 0x500317 in vectorstream_test() /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:108:10
#2 0x4fa2d3 in main /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:179:7
#3 0x7fc25ace62e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
#4 0x420319 in _start (/home/debian/boost-root/bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test+0x420319)
0x62600000360a is located 1290 bytes inside of 10000-byte region [0x626000003100,0x626000005810)
allocated by thread T0 here:
#0 0x4f73b2 in operator new(unsigned long) /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/asan_new_delete.cc:106:3
#1 0x5264d8 in std::__1::__libcpp_allocate(unsigned long, unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/new:252:10
#2 0x5264d8 in std::__1::allocator<char>::allocate(unsigned long, void const*) /usr/lib/llvm-7/bin/../include/c++/v1/memory:1799
#3 0x5264d8 in std::__1::allocator_traits<std::__1::allocator<char> >::allocate(std::__1::allocator<char>&, unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/memory:1548
#4 0x5264d8 in std::__1::__split_buffer<char, std::__1::allocator<char>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<char>&) /usr/lib/llvm-7/bin/../include/c++/v1/__split_buffer:311
#5 0x531ac9 in std::__1::vector<char, std::__1::allocator<char> >::reserve(unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/vector:1574:53
#6 0x50b6d7 in boost::interprocess::basic_vectorbuf<std::__1::vector<char, std::__1::allocator<char> >, std::__1::char_traits<char> >::reserve(unsigned long) /home/debian/boost-root/./boost/interprocess/streams/vectorstream.hpp:158:17
#7 0x50b464 in boost::interprocess::basic_vectorstream<std::__1::vector<char, std::__1::allocator<char> >, std::__1::char_traits<char> >::reserve(unsigned long) /home/debian/boost-root/./boost/interprocess/streams/vectorstream.hpp:598:17
#8 0x4ff975 in vectorstream_test() /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:101:23
#9 0x4fa2d3 in main /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:179:7
#10 0x7fc25ace62e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0.
If you suspect a false positive see also: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow.
SUMMARY: AddressSanitizer: container-overflow /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:432:3 in __interceptor_strcmp
Shadow bytes around the buggy address:
0x0c4c7fff8670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff8680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff8690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff86a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff86b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c4c7fff86c0: 00[02]fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86d0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86e0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86f0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff8700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff8710: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==19941==ABORTING
$ ./b2 toolset=clang-7 sanitize=address variant=debug libs/interprocess/test//vectorstream_test stdlib=libc++ -d+2 2>&1 | tee vectorstream_test.log
Performing configuration checks
- default address-model : 64-bit
- default architecture : x86
- symlinks supported : yes
common.mkdir bin.v2/libs
mkdir -p "bin.v2/libs"
common.mkdir bin.v2/libs/interprocess
mkdir -p "bin.v2/libs/interprocess"
common.mkdir bin.v2/libs/interprocess/test
mkdir -p "bin.v2/libs/interprocess/test"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi"
common.mkdir bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden
mkdir -p "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden"
clang-linux.compile.c++.without-pch bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.o
"clang++-7" -c -x c++ -fvisibility-inlines-hidden -fPIC -m64 -pthread -O0 -fno-inline -Wall -g -fvisibility=hidden -fsanitize=address -stdlib=libc++ -DBOOST_ALL_NO_LIB=1 -I"." -o "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.o" "libs/interprocess/test/vectorstream_test.cpp"
clang-linux.link bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test
"clang++-7" -o "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test" -Wl,--start-group "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.o" -Wl,-Bstatic -Wl,-Bdynamic -lrt -Wl,--end-group -fPIC -m64 -pthread -g -fvisibility=hidden -fvisibility-inlines-hidden -fsanitize=address -lrt -stdlib=libc++
testing.capture-output bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.run
status=0
if test $status -ne 0 ; then
echo Skipping test execution due to testing.execute=off
exit 0
fi
"bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test" > "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.output" 2>&1 < /dev/null
status=$?
echo >> "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.output"
echo EXIT STATUS: $status >> "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.output"
if test $status -eq 0 ; then
cp "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.output" "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.run"
fi
verbose=0
if test $status -ne 0 ; then
verbose=1
fi
if test $verbose -eq 1 ; then
echo ====== BEGIN OUTPUT ======
cat "bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test.output"
echo ====== END OUTPUT ======
fi
exit $status
====== BEGIN OUTPUT ======
=================================================================
==19941==ERROR: AddressSanitizer: container-overflow on address 0x62600000360a at pc 0x00000043496a bp 0x7ffc8aded210 sp 0x7ffc8adec998
READ of size 1291 at 0x62600000360a thread T0
#0 0x434969 in __interceptor_strcmp /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:432:3
#1 0x500317 in vectorstream_test() /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:108:10
#2 0x4fa2d3 in main /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:179:7
#3 0x7fc25ace62e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
#4 0x420319 in _start (/home/debian/boost-root/bin.v2/libs/interprocess/test/vectorstream_test.test/clang-linux-7/debug/sanitize-address/stdlib-libc++/threading-multi/visibility-hidden/vectorstream_test+0x420319)
0x62600000360a is located 1290 bytes inside of 10000-byte region [0x626000003100,0x626000005810)
allocated by thread T0 here:
#0 0x4f73b2 in operator new(unsigned long) /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/asan_new_delete.cc:106:3
#1 0x5264d8 in std::__1::__libcpp_allocate(unsigned long, unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/new:252:10
#2 0x5264d8 in std::__1::allocator<char>::allocate(unsigned long, void const*) /usr/lib/llvm-7/bin/../include/c++/v1/memory:1799
#3 0x5264d8 in std::__1::allocator_traits<std::__1::allocator<char> >::allocate(std::__1::allocator<char>&, unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/memory:1548
#4 0x5264d8 in std::__1::__split_buffer<char, std::__1::allocator<char>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<char>&) /usr/lib/llvm-7/bin/../include/c++/v1/__split_buffer:311
#5 0x531ac9 in std::__1::vector<char, std::__1::allocator<char> >::reserve(unsigned long) /usr/lib/llvm-7/bin/../include/c++/v1/vector:1574:53
#6 0x50b6d7 in boost::interprocess::basic_vectorbuf<std::__1::vector<char, std::__1::allocator<char> >, std::__1::char_traits<char> >::reserve(unsigned long) /home/debian/boost-root/./boost/interprocess/streams/vectorstream.hpp:158:17
#7 0x50b464 in boost::interprocess::basic_vectorstream<std::__1::vector<char, std::__1::allocator<char> >, std::__1::char_traits<char> >::reserve(unsigned long) /home/debian/boost-root/./boost/interprocess/streams/vectorstream.hpp:598:17
#8 0x4ff975 in vectorstream_test() /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:101:23
#9 0x4fa2d3 in main /home/debian/boost-root/libs/interprocess/test/vectorstream_test.cpp:179:7
#10 0x7fc25ace62e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
HINT: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0.
If you suspect a false positive see also: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow.
SUMMARY: AddressSanitizer: container-overflow /build/llvm-toolchain-7-7.0.1~svn348686/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:432:3 in __interceptor_strcmp
Shadow bytes around the buggy address:
0x0c4c7fff8670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff8680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff8690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff86a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4c7fff86b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c4c7fff86c0: 00[02]fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86d0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86e0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff86f0: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff8700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
0x0c4c7fff8710: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==19941==ABORTING
EXIT STATUS: 1
====== END OUTPUT ======
...failed updating 1 target...
Why does documentation omits method’s input variable’s names in Synopsis
section?
For example:
https://www.boost.org/doc/libs/1_69_0/doc/html/boost/interprocess/mapped_region.html
class mapped_region {
...
bool flush(std::size_t = 0, std::size_t = 0, bool = true);
...
}
This looks bad for me, because there’s no way to understand the meaning of size_t
s or bool
. I think this synopsis doesn’t help as much as it could.
Hopefully, there is more appropriate description below:
bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0,
bool async = true);
I think it would be good to have this in synopsis.
when segment.find<>("").first; gives error
how to fix that?
v1.64
Hi,
I have a simple project running under Windows. It consists of two DLLs and one EXE. The EXE loads the two DLLs. Each will create a shared memory object in a class instatiated by a std::unique_ptr globaly. The crash happens during FreeLibrary and only if I use the /MTd switch (Multi-threaded Debug) instead of /MDd (Multi-threaded Debug DLL).
I built boost libs using:
b2.exe -a -j %NUMBER_OF_PROCESSORS% --prefix=%BOOST% --libdir=%BOOST%/lib/x86 --reconfigure --build-type=complete --toolset=msvc-14.2 link=static address-model=32 runtime-link=static runtime-link=shared threading=multi define=BOOST_USE_WINDOWS_H define=NOMINMAX install
where %BOOST%
points to my BOOST installation folder.
The example code can be downloaded here.
Kind regards and many thanks for your great work, Christian.
I am having issues in using boost::interprocess
to store the content of a huge std::vector
on a memory mapped file. For instance, it crashes in debug mode.
By reading the boost::interprocess
documentation, it is not totally clear to me if I must adopt the provided boost
STL-like containers, or I can also directly use STL containers for modern compilers (I mainly need to use MSVC14).
Given that I use SWIG to bind my library on Python (3.6 thus MSVC14), it would be simpler for me to stick with the official STL containers (so that I can use the bundled SWIG interface files).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.