In perl.git, the branch tonyc/133958-realloc-errno-success has been created
<https://perl5.git.perl.org/perl.git/commitdiff/9f300641fc6fb15749f287d7ac7fd6f312b3edd8?hp=0000000000000000000000000000000000000000> at 9f300641fc6fb15749f287d7ac7fd6f312b3edd8 (commit) - Log ----------------------------------------------------------------- commit 9f300641fc6fb15749f287d7ac7fd6f312b3edd8 Author: Tony Cook <[email protected]> Date: Fri May 3 14:49:50 2019 +1000 (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(). ----------------------------------------------------------------------- -- Perl5 Master Repository
