Ok, as Adrien suggested, the problem appears to occur when two child
processes of a parent process request the same exact address (displaying
relevant parts of strace -t):
[ 1044] _kern_normalize_path("/boot/system/non-packaged/lib/cpp", true,
0x72fee2f8) = 0x00000000 No error (21 us)
[ 1044] _kern_read(0x4, 0x0, 0x72fed2c4, 0x34) = 0x00000034 (4 us)
[ 1044] _kern_read(0x4, 0x34, 0x72fed2f8, 0xa0) = 0x000000a0 (2 us)
[ 1044] _kern_reserve_address_range([0x200000], 0x1, 0x2e000) =
0x00000000 No error (2 us)
...
[ 1046] _kern_normalize_path("/boot/system/non-packaged/lib/ccom",
true, 0x72ad6238) = 0x00000000 No error (21 us)
[ 1046] _kern_read(0x4, 0x0, 0x72ad5204, 0x34) = 0x00000034 (4 us)
[ 1046] _kern_read(0x4, 0x34, 0x72ad5238, 0xa0) = 0x000000a0 (3 us)
[ 1046] _kern_reserve_address_range([0x200000], 0x1, 0x67000) =
0x80000005 Invalid Argument (2 us)
[ 1046] _kern_debug_output("runtime_loader:
/boot/system/non-packaged/lib/ccom: Could not map image: Out of memory
") (301 us)
[ 1046] _kern_write(0x2, 0x0, 0x72ad4da8, 0x57) = 0x00000057 (11 us)
[ 1046] _kern_close(0x4) = 0x00000000 No error (3 us)
[ 1046] _kern_loading_app_failed(0xffffffff) (3 us)
Digging really deep into how strace could be returning B_BAD_VALUE
(INT_MIN + 5)
from _[kernel|user]_reserve_address_range (calling parameters omitted
for clarity):
system/kernel/vm/vm.cpp
status_t
_user_reserve_address_range()
{
--> status_t status = vm_reserve_address_range(
VMAddressSpace::CurrentID(), (void**)&address,
addressSpec, size, RESERVED_AVOID_BASE);
if (status != B_OK)
return status;
...
}
status_t
vm_reserve_address_range(team_id team, void** _address, uint32
addressSpec, addr_t size, uint32 flags)
{
...
--> return addressSpace->ReserveAddressRange()
...
}
system/kernel/vm/VMUserAddressSpace.cpp
status_t
VMUserAddressSpace::ReserveAddressRange()
{
...
--> status_t status = InsertArea(area, size, addressRestrictions,
allocationFlags, _address);
if (status != B_OK) {
area->~VMUserArea();
free_etc(area, allocationFlags);
return status;
}
}
status_t
VMUserAddressSpace::InsertArea()
{
...
--> status = _InsertAreaSlot(searchBase, size, searchEnd,
addressRestrictions->address_specification,
addressRestrictions->alignment, area, allocationFlags);
if (status == B_OK) {
if (_address != NULL)
*_address = (void*)area->Base();
fFreeSpace -= area->Size();
}
return status;
}
status_t
VMUserAddressSpace::_InsertAreaSlot()
{
...
if (addressSpec == B_EXACT_ADDRESS && area->id != RESERVED_AREA_ID) {
// search for a reserved area
status_t status = _InsertAreaIntoReservedRegion(start, size, area,
allocationFlags);
if (status == B_OK || status == B_BAD_VALUE)
return status;
...
case B_EXACT_ADDRESS:
// see if we can create it exactly here
if ((last == NULL || last->Base() + (last->Size() - 1) < start)
&& (next == NULL || next->Base() > start + (size - 1))) {
foundSpot = true;
area->SetBase(start);
break;
}
break;
default:
return B_BAD_VALUE;
}
if (!foundSpot)
return addressSpec == B_EXACT_ADDRESS ? B_BAD_VALUE : B_NO_MEMORY;
...
}
status_t
VMUserAddressSpace::_InsertAreaIntoReservedRegion()
{
VMUserArea* next;
...
for (VMUserAreaList::Iterator it = fAreas.GetIterator();
(next = it.Next()) != NULL;) {
if (next->Base() <= start && next->Base() + (next->Size() - 1) >=
start + (size - 1)) {
// This area covers the requested range
if (next->id != RESERVED_AREA_ID) {
// but it's not reserved space, it's a real area
return B_BAD_VALUE;
...
}
Basically, there are two different places B_BAD_VALUE could be returned
(which strace looks up as EINVAL and returns a conflicting message to
the Out of Memory/B_NO_MEMORY message runtime_loader returns).
The problem, though, is that the other child process that had requested
that area is supposed to have exited:
[ 1042] _kern_wait_for_child(0x414, 0x0, 0x72bb81f8) = 0x00000414
(126849 us)
[ 1042] --- Child exited (Child exited) ---
[ 1042] _kern_read_stat(0xffffffff, "/tmp", true, 0x72bb81d8, 0x58) =
0x00000000 No error (13 us)
[ 1042] _kern_open(0xffffffff, "/tmp/ctm.9QlBqW", 0x302, 0x180) =
0x00000004 (177 us)
[ 1042] _kern_close(0x4) = 0x00000000 No error (4 us)
[ 1042] _kern_access(0xffffffff, "/system/non-packaged/lib/ccom", 0x1,
false) = 0x00000000 No error (12 us)
[ 1046] _kern_area_for(0x18372000) = 0x0000ca88 (0 us)
[ 1042] _kern_fork() = 0x00000416 (840 us)
Sometimes, though, the above code works perfectly fine and no errors are
encountered. Is this a timing issue, in that sometimes the address
space has been cleared and sometimes it has not?
tim