(perl #133958) preserve errno on successful malloc/realloc
In general perl doesn't try to preserve errno (aka $!) since we're
aiming at the same behaviour as for C code - errno is only meaningful
if a function returned an error.
The exception to that is when perl is working without an explicit
request from the perl programmer.
When code is performing assignments, concatenating strings, pushing on
arrays etc, perl is exercising the memory allocation machinery,
calling malloc() and realloc().
It turns out that at least on one platform, realloc() can modify errno
on success.
It appears to be happening when jemalloc (the malloc() implementation
used on FreeBSD) tries to extend a memory arena and fails, leaving the
error number from that failure in errno, from truss:
mmap(0x80142f000,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANON|MAP_EXCL,-1,0x0) ERR#12 'Cannot allocate memory'
This magic call appears to be a FreeBSD specific mechanism to resize
the anonymous mapping. On Linux the equivalent seems to be calling
mremap().
In each case for the test code mmap() is successfully called
immediately afterwards:
mmap(0x0,69632,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON|MAP_ALIGNED(12),-1,0x0) =
34390323200 (0x801d2b000)
and realloc() succeeds.
glibc() realloc seems to be simpler, AFAICT from reading the code it
only uses mremap() when the memory block is the entire mapping,
ie. for large blocks rather than for memory arenas, and it doesn't
request the same address, so it doesn't fail.
For blocks that are part of arenas, glibc tries to expand in-place
within the current arena (with no extending the arena itself) or falls
back to malloc, so there's no chance for errno to be changed on a
successful realloc().