[Interprocess] error_code_t = 9 (already_exists_error) while opening a fixed_managed_shared_memory
Hello Ion and other Interprocess users, we are currently working with fixed_managed_shared_memory segments and we have a strange behavior while opening existing segments. Sometimes (we did not found the exact scenario yet...), when we try to open a fixed_managed_shared_memory in open_only mode with the code below, we get an interprocess_exception with the an error_code_t = 9 ( already_exists_error ). try{ managedSharedMemorySegment = new fixed_managed_shared_memory(boost::interprocess::open_only, memorySegmentName, memorySegmentMappingAdress); }catch (boost::interprocess::interprocess_exception e){ return e.get_error_code(); } A first sight this error_code seems very strange, because in open_only mode the segment is intended to already exists so that should not be an error. Walking the code I found in the mapped_region constructor the following code which trigger the exception : 522: //Check for fixed mapping error if(address && (old_base != address)){ error_info err = system_error_code(); this->priv_close(); throw interprocess_exception(err); } It seems that the mmap function returns an address different that the given one, which is considered an error. So I have two questions : 1) Do you have an idea why the mmap function maps the segment at a different address from the provided one, knowing that this address is the one returned from code below on another process (so should be valid) ? try{ managedSharedMemorySegment = new fixed_managed_shared_memory(boost::interprocess::create_only, memorySegmentName, memorySegmentSize); memorySegmentMappingAdress = managedSharedMemorySegment->get_address(); }catch (boost::interprocess::interprocess_exception e){ return e.get_error_code(); } 2) In the mapped_region constructor, when a non null address value is given as a parameter, could we use the MAP_FIXED flag to force the mmap function to map the segment at the provided address ? Thank you for reading and for your help. Gaëtan
On 05/19/2011 10:52 AM, Gaetan Gaumer wrote:
So I have two questions : 1) Do you have an idea why the mmap function maps the segment at a different address from the provided one, knowing that this address is the one returned from code below on another process (so should be valid) ?
Perhaps that address space was already being used by something. This is likely to be the case with large regions on a 32-bit OS. How large is is the segment you're trying to map? Is your process running as 64- or 32-bits?
2) In the mapped_region constructor, when a non null address value is given as a parameter, could we use the MAP_FIXED flag to force the mmap function to map the segment at the provided address ?
What happens if something else is already at that address? - Marsh
2011/5/19 Marsh Ray
On 05/19/2011 10:52 AM, Gaetan Gaumer wrote:
So I have two questions : 1) Do you have an idea why the mmap function maps the segment at a different address from the provided one, knowing that this address is the one returned from code below on another process (so should be valid) ?
Perhaps that address space was already being used by something. This is likely to be the case with large regions on a 32-bit OS.
It's indeed used by something as it is the address of the segment return by a new fixed_managed_shared_memory(boost::interprocess::create_only,...)
How large is is the segment you're trying to map?
Currently 250MB but we want to use bigger segments soon.
Is your process running as 64- or 32-bits?
64 bits
2) In the mapped_region constructor, when a non null address value is given as a parameter, could we use the MAP_FIXED flag to force the mmap function to map the segment at the provided address ?
What happens if something else is already at that address?
According to mmap spec (http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html) "mmap() may return MAP_FAILED and set errno to [EINVAL]" But in our case the address is used by the segment we want to open...
On 05/19/2011 11:26 AM, Gaetan Gaumer wrote:
2011/5/19 Marsh Ray
: Perhaps that address space was already being used by something. This is likely to be the case with large regions on a 32-bit OS.
It's indeed used by something as it is the address of the segment return by a new fixed_managed_shared_memory(boost::interprocess::create_only,...)
But that was in another process, right? In general, mappings in process A do not reserve that same address region in other processes. There are some OS-specific exceptions. If this were not the case, a process which mapped all the free regions in its own address space would cause problems for every other process in the system.
Currently 250MB but we want to use bigger segments soon. 64 bits
Ought to be fine.
What happens if something else is already at that address?
According to mmap spec (http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html) "mmap() may return MAP_FAILED and set errno to [EINVAL]"
Right, it fails.
But in our case the address is used by the segment we want to open...
Again, that's a different process and each has its own address space. Unless I'm misunderstanding your design. - Marsh
El 19/05/2011 17:52, Gaetan Gaumer escribió:
Hello Ion and other Interprocess users, we are currently working with fixed_managed_shared_memory segments and we have a strange behavior while opening existing segments. Sometimes (we did not found the exact scenario yet...), when we try to open a fixed_managed_shared_memory in open_only mode with the code below, we get an interprocess_exception with the an error_code_t = 9 ( already_exists_error ).
That error does not seem the correct answer to the problem.
Walking the code I found in the mapped_region constructor the following code which trigger the exception : 522: //Check for fixed mapping error if(address&& (old_base != address)){ error_info err = system_error_code(); this->priv_close(); throw interprocess_exception(err); }
I think that system_error_code() call is wrong. Mmap was succesful, but suggested address was not used (MAP_FIXED is not used, because it removes previous mapping in that address and the portable semantics of mapped_region need to return an error if that address could not be used). So the OS should not be called for an error. You can replace that line, maybe with something like: error_info err(busy_error);
So I have two questions : 1) Do you have an idea why the mmap function maps the segment at a different address from the provided one, knowing that this address is the one returned from code below on another process (so should be valid) ?
Every address can be different in each process. Shared memory, in some systems, shares address space with DLLs and other goodies. Depending on your memory map when you call mmap, the address chosen by each process might be different.
2) In the mapped_region constructor, when a non null address value is given as a parameter, could we use the MAP_FIXED flag to force the mmap function to map the segment at the provided address ?
That would break portable semantics, we want mapped_region to fail if the address was used, otherwise, you might be unmapping DLL code or any other previous mapping (mapped file, etc.) and bad things will happen. MAP_FIXED is IMHO usable only to map devices/video memory that you know exactly where they are placed in your system. Best, Ion
Hello again, For more information, we're working on a Linux x64 (RHEL 5.4) with Boost 1.45 [...]
So I have two questions : 1) Do you have an idea why the mmap function maps the segment at a different address from the provided one, knowing that this address is the one returned from code below on another process (so should be valid) ?
Every address can be different in each process. Shared memory, in some systems, shares address space with DLLs and other goodies. Depending on your memory map when you call mmap, the address chosen by each process might be different.
But for fixed_managed_shared_memory the segment must be mapped at the same address, isn't it ? That's what is explained in the doc : http://www.boost.org/doc/libs/1_46_0/doc/html/interprocess/managed_memory_se... "The user can also map the managed shared memory in a fixed address. This option is essential when using using fixed_managed_shared_memory" (typo inside) If two processes can't be sure to be able to map the segment at the same address then fixed_managed_shared_memory seems to be useless.
2) In the mapped_region constructor, when a non null address value is given as a parameter, could we use the MAP_FIXED flag to force the mmap function to map the segment at the provided address ?
That would break portable semantics, we want mapped_region to fail if the address was used, otherwise, you might be unmapping DLL code or any other previous mapping (mapped file, etc.) and bad things will happen. MAP_FIXED is IMHO usable only to map devices/video memory that you know exactly where they are placed in your system.
What I still don't understand is why sometimes that's work well and sometimes it fails. If the system consider that the memory address is used by another process, then it should fail every time ( and then fixed_managed_shared_memory should not be unusable at all). I'll further investigate the usecase which conduce to the error to see if we're doing something wrong. As we're working on Linux, do you think that using xsi_shared_memory could help ? Is there a fixed_managed_xsi_shared_memory ? I think the last option is to switch to basic_managed_shared_memory and work with offset pointers but I dont't like this option especially knowing that fixed_managed_shared_memory should work and meet our needs. Thanks for you help, Gaëtan
On Fri, 20 May 2011 10:15:52 +0200, Gaetan Gaumer
El 20/05/2011 10:15, Gaetan Gaumer escribió:
If two processes can't be sure to be able to map the segment at the same address then fixed_managed_shared_memory seems to be useless.
You have the same problem with mmap or MapViewOfFile in windows. The application must be sure that address range free. It's not an Interprocess issue. Depending on your system, you might know which address might be free (maybe your OS allocates new address range in a well-known way, and you know which range will be surely free).
As we're working on Linux, do you think that using xsi_shared_memory could help ?
You have the same issue. Address range is allocated by the OS for several resources and the allocation depends on what the application loads. Fixed mapping is not very usable unless you control your environment very well. And for some security reasons (making things more difficult to hackers), the loader might load your application in a different address each time you start: http://en.wikipedia.org/wiki/Address_space_layout_randomization Best, Ion
On 05/20/2011 03:15 AM, Gaetan Gaumer wrote:
If two processes can't be sure to be able to map the segment at the same address then fixed_managed_shared_memory seems to be useless.
Yes, in general I would not use fixed address shared memory. There are special circumstances where one might need it: * You might reserve the memory in one process and then fork(), ensuring that the child process has the same memory layout. * You may be able to pre-reserve address regions before anything else gets mapped in your process. * You may be using special kernel facilities or hardware devices that guarantee the memory range will be accepted. Maybe the docs could help new users by discussing these drawbacks a little more prominently? - Marsh
2011/5/20 Marsh Ray
On 05/20/2011 03:15 AM, Gaetan Gaumer wrote:
If two processes can't be sure to be able to map the segment at the same address then fixed_managed_shared_memory seems to be useless.
Yes, in general I would not use fixed address shared memory.
There are special circumstances where one might need it:
* You might reserve the memory in one process and then fork(), ensuring that the child process has the same memory layout. * You may be able to pre-reserve address regions before anything else gets mapped in your process. * You may be using special kernel facilities or hardware devices that guarantee the memory range will be accepted.
So, as I'm not in one of these cases I should use managed_shared_memory instead of fixed_managed_shared_memory
Maybe the docs could help new users by discussing these drawbacks a little more prominently?
Yes, I think it would be helpful. Thanks all for your explanations. Cheers, Gaëtan
participants (4)
-
Gaetan Gaumer
-
Ion Gaztañaga
-
Marsh Ray
-
Viatcheslav.Sysoltsev@h-d-gmbh.de