using glibc malloc hooks in a thread safe manner

Alex Brown picture Alex Brown · Jan 7, 2010 · Viewed 9.7k times · Source

I would like to monitor the use of mallocs and frees in an application by using the malloc and free hooks.

Here's the documentation http://www.gnu.org/s/libc/manual/html_node/Hooks-for-Malloc.html

From the example page you can see that my_malloc_hook transiently switches the malloc hook off (or to the previous hook in the chain) before re-invoking malloc.

This is a problem when monitoring multi-threaded applications (see end of question for explanation).

Other examples of the use of malloc hook that I have found on the internet have the same problem.

Is there a way to re-write this function to work correctly in a multi-threaded application?

For instance, is there an internal libc function that the malloc hook can invoke that completes the allocation, without the need to deactivate my hook.

I can't look at the libc source code due to corporate legal policy, so the answer may be obvious.

My design spec says I cannot replace malloc with a different malloc design.

I can assume that no other hooks are in play.


UPDATE

Since the malloc hook is temporarily removed while servicing the malloc, another thread may call malloc and NOT get the hook.

It has been suggested that malloc has a big lock around it that prevents this from happening, but it's not documented, and the fact that I effectively recursively call malloc suggests any lock must either exist after the hook, or be jolly clever:

caller -> 
  malloc -> 
    malloc-hook (disables hook) -> 
      malloc -> # possible hazard starts here
        malloc_internals
      malloc <-
    malloc-hook (enables hook) <-
  malloc
caller

Answer

Will picture Will · Jan 7, 2010

UPDATED

You are right to not trust __malloc_hooks; I have glanced at the code, and they are - staggeringly crazily - not thread safe.

Invoking the inherited hooks directly, rather than restoring and re-entering malloc, seems to be deviating from the the document you cite a little bit too much to feel comfortable suggesting.

From http://manpages.sgvulcan.com/malloc_hook.3.php:

Hook variables are not thread-safe so they are deprecated now. Programmers should instead preempt calls to the relevant functions by defining and exporting functions like "malloc" and "free".

The appropriate way to inject debug malloc/realloc/free functions is to provide your own library that exports your 'debug' versions of these functions, and then defers itself to the real ones. C linking is done in explicit order, so if two libraries offer the same function, the first specified is used. You can also inject your malloc at load-time on unix using the LD_PRELOAD mechanisms.

http://linux.die.net/man/3/efence describes Electric Fence, which details both these approaches.

You can use your own locking if in these debug functions if that is necessary.