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

Reply via email to