This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 71321841eb GH-40900: [Go] Fix Mallocator Weirdness (#40902)
71321841eb is described below

commit 71321841eb6d94946de43cccb7f04afe5cf2aa10
Author: Matt Topol <[email protected]>
AuthorDate: Mon Apr 1 11:15:59 2024 -0400

    GH-40900: [Go] Fix Mallocator Weirdness (#40902)
    
    
    
    ### Rationale for this change
    With help from @ lidavidm and @ bkietz digging into the linked issue, we 
found the following:
    
    * Using `mtrace` and `strace` didn't produce much enlightenment to what was 
happening.
    * If the python adbc_driver_manager was built so that the cython lib is 
built using `CMAKE_BUILD_TYPE=Debug` then the crash/failure goes away
    * If the env var `MALLOC_MMAP_THRESHOLD_` is set to 128MB, the 
crash/failure goes away
    * It is only reproducible when calling through python, I haven't been able 
to reproduce it using pure Go
    * Calling `calloc` again after it fails, still fails
    * Calling `malloc` + `memset` immediately after the failing `calloc` works 
perfectly and doesn't fail anymore
    
    ### What changes are included in this PR?
    Adding a comment describing the situation and falling back to `malloc` + 
`memset` if `calloc` returns an error. If the pointer returned from `malloc` is 
`nil` then we surface the error.
    
    * GitHub Issue: #40900
    
    Authored-by: Matt Topol <[email protected]>
    Signed-off-by: Matt Topol <[email protected]>
---
 go/arrow/memory/mallocator/mallocator.go | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/go/arrow/memory/mallocator/mallocator.go 
b/go/arrow/memory/mallocator/mallocator.go
index 59d240a106..9483bdfc2a 100644
--- a/go/arrow/memory/mallocator/mallocator.go
+++ b/go/arrow/memory/mallocator/mallocator.go
@@ -60,10 +60,19 @@ func (alloc *Mallocator) Allocate(size int) []byte {
        }
        ptr, err := C.calloc(C.size_t(size), 1)
        if err != nil {
-               panic(err)
+               // under some circumstances and allocation patterns, we can end 
up in a scenario
+               // where for some reason calloc return ENOMEM even though there 
is definitely memory
+               // available for use. So we attempt to fallback to simply doing 
malloc + memset in
+               // this case. If malloc returns a nil pointer, then we know 
we're out of memory
+               // and will surface the error.
+               if ptr = C.malloc(C.size_t(size)); ptr == nil {
+                       panic(err)
+               }
+               C.memset(ptr, 0, C.size_t(size))
        } else if ptr == nil {
                panic("mallocator: out of memory")
        }
+
        atomic.AddUint64(&alloc.allocatedBytes, uint64(size))
        return unsafe.Slice((*byte)(ptr), size)
 }

Reply via email to