Skip to content

App linked against jemalloc crashes freeing result of realpath #226

Closed

Description

@nchaimov

After fixing #225, the E4S chapel no longer hangs at startup, but the test instead segfaults later during execution. The problem occurs when the Chapel runtime calls realpath with resolved_path = NULL. Upon freeing the realpath-allocated return value, there is a crash in jemalloc.

Can be reproduced in serial CI container:

spindleuser@spindlenode:~$ sudo apt install libjemalloc-dev
[...]
spindleuser@spindlenode:~$ cat -n test.c
     1  #include <stdlib.h>
     2  #include <stdio.h>
     3
     4  int main(void) {
     5     char *r = realpath("/proc/self/exe", NULL);
     6     if (!r) {
     7       fprintf(stderr, "realpath returned NULL\n");
     8       return 1;
     9     }
    10     fprintf(stderr, "realpath = %s\n", r);
    11     free(r);
    12     fprintf(stderr, "OK\n");
    13     return 0;
    14  }
spindleuser@spindlenode:~$ gcc -g -o test_system_malloc test.c
spindleuser@spindlenode:~$ gcc -g -o test_jemalloc test.c -ljemalloc
spindleuser@spindlenode:~$ ./test_system_malloc
realpath = /home/spindleuser/test_system_malloc
OK

spindleuser@spindlenode:~$ ./test_jemalloc
realpath = /home/spindleuser/test_jemalloc
OK

spindleuser@spindlenode:~$ spindle ./test_system_malloc
realpath = /home/spindleuser/test_system_malloc
OK

spindleuser@spindlenode:~$ spindle --level=off ./test_jemalloc
realpath = /home/spindleuser/test_jemalloc
OK

spindleuser@spindlenode:~$ spindle --level=low ./test_jemalloc
realpath = /home/spindleuser/test_jemalloc
spindleuser@spindlenode:~$ ls core.*
core.test_jemalloc.1938

The backtrace shows the crash on line 11, in the call to free:

#0  0x00007c674849018a in ?? () from /lib/x86_64-linux-gnu/libjemalloc.so.2
#1  0x00005e21bc02c22c in main () at test.c:11

It appears that Spindle is allocating with the malloc from libc, which then causes a crash in jemalloc's free when it is passed an address allocated by libc, not jemalloc

Activity

  1. mplegendre commented on Oct 2, 2026

    @mplegendre
    Member

    Aw. That makes sense and an issue. When emulating some of the calls like realpath() we hardcode to calling malloc in libc. But instead we need to search-for and use the same malloc that the app is referencing. I think you've got a couple choices:

    • Do an in-order search of the link maps checking each DSO if it exports the malloc family, and make the first one found our malloc instance.
    • IIRC, the symbind LD_AUDIT callbacks can tell you what symbol instance was being bound to. When we see one of those for a malloc family, we start using that instance for spindle's calls.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions