2

I am trying to use jemalloc for memory profiling, due to some reason i don't have control of parent process, So instead of setting MALLOC_CONF env variable outside, i am trying to set the variable within the program, but seems its not working.

I have tried setting the MALLOC_CONF env outside and then launch the process.. it works.

Below is the snippet of sample program

void keep_mallocing(int count, size_t size, int **ptr) {
        int i =0;
        for(i=0; i<count; i++) {
                ptr[i] = malloc(size);
                memset(ptr[i], 0, size);
        }
}

void keep_freeing(int count, int **ptr) {
        int i = 0;
        for(i=0; i<count; i++) {
                free(ptr[i]);
        }
}

void handle_sigusr1(int sig)
{
//      malloc_stats_print(NULL, NULL, "g,l,b,h,m,a");

        char *path = 0;
        path = getenv( "MALLOC_CONF" );
        printf("path : %s\n", path);

        mallctl("prof.dump", NULL, NULL, NULL, 0);
        return;
}

int
main(int argc, char **argv) {

        signal(SIGUSR1, handle_sigusr1);
        setenv("MALLOC_CONF", "prof:true,prof_prefix:jeprof.out", 1);
        while(1)
        {
                int *ptr[10] = {0};
                // count, bytes, ptr
                keep_mallocing(10, 1000000, ptr);

                sleep (1);
                // count, ptr
                keep_freeing(7, ptr);
                sleep (5);
        }

    return 0;
}

I m using below command to compile the code (I have tried both static and dynamic linking)

gcc -ggdb3 use_jemalloc.c -std=gnu99 -o abc /usr/local/lib/libjemalloc.a -lpthread -ldl -lm

If i export the variable and then run things seems to be working

$ ls
abc  use_jemalloc.c

$ export MALLOC_CONF="prof:true,prof_prefix:jeprof.out"

$ ./abc &
[1] 23220

$ kill -10 `pidof abc`
path : prof:true,prof_prefix:jeprof.out

$ ls
abc  jeprof.out.23220.0.m0.heap  use_jemalloc.c

But if u nullify the variable and then it doesn't generate anything

$ rm jeprof.*

$ ls
abc  use_jemalloc.c

$ export MALLOC_CONF=
$ echo $MALLOC_CONF


$ ./abc &
[1] 23244

$ kill -10 `pidof abc`
path : prof:true,prof_prefix:jeprof.out

$ ls
abc  use_jemalloc.c
Ronin Goda
  • 234
  • 5
  • 13
  • 1
    Your signal handler invokes undefined behavior. Per [**7.1.4 Use of library functions**, paragraph 4 of the C standard](https://port70.net/~nsz/c/c11/n1570.html#7.1.4p4): "The functions in the standard library are not guaranteed to be reentrant and may modify objects with static or thread storage duration." [Footnote 188 adds](https://port70.net/~nsz/c/c11/n1570.html#note188): "Thus, a signal handler cannot, in general, call standard library functions." [POSIX allows calling async-signal-safe functions.](https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03) – Andrew Henle Sep 11 '19 at 11:23
  • 2
    (cont) But neither `getenv()` nor `printf()` are async-signal-safe. And I seriously doubt that `mallctl()` is async-signal-safe either. – Andrew Henle Sep 11 '19 at 11:24
  • @AndrewHenle - i will keep that in mind.. getnev and printf was used only to show the variable.. ideally there would be only mallctl called. – Ronin Goda Sep 11 '19 at 11:35
  • 2
    `jemalloc` only checks this when it starts up. – S.S. Anne Sep 11 '19 at 11:38
  • @JL2210 - U mean even before main() function ? – Ronin Goda Sep 11 '19 at 11:44
  • 1
    @RoninGoda Yes -- I would assume that it uses constructors and destructors even before `main`. – S.S. Anne Sep 11 '19 at 11:45
  • So basically u r saying there is no way to achieve this ? – Ronin Goda Sep 11 '19 at 11:49
  • @RoninGoda Curious to know how you finally achieve this? – ashish Apr 07 '20 at 07:03

1 Answers1

4

If jemalloc only checks the value on startup, you can check if the MALLOC_CONF environment variable is not set, and if it's not set you can set it and re-exec to restart your process with the environment variable set:

#include <unistd.h>
#include <stdlib.h>

int main( int argc, char **argv )
{
    char *envval = getenv( "MALLOC_CONF" );
    if ( NULL == envval )
    {
        setenv( "MALLOC_CONF", "prof:true,prof_prefix:jeprof.out", 1 );
        execv( argv[ 0 ], argv );
    }

    ...
}

Note that this may cause problems if the code that runs prior to main() does things like open files and leave them open. That isn't likely.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56