Skip to content

Infinite loop if malloc used in signal handler #8

@plujon

Description

@plujon

I am using lockfree-malloc because I want an implementation of malloc I can use in a signal handler. However, I have discovered a race condition in lockfree-malloc that leads to an infinite loop in some circumstances. Below is a test case that demonstrates the problem, generally in fewer than 15 tries on my Phenom II CPU. You'll know the bug has been hit when the CPU starts to spin.

/*
 * Provoke race condition infinite-loop in lockfree-malloc singleton.
 * When a signal is delivered while the first malloc call is in
 * progress, with the right timing, neither call to malloc will ever
 * return.  Instead, the CPU will spin forever.
 */
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int which_signal = SIGHUP;

void *__wrap_malloc(size_t size);

void handler(int signum)
{
  void *p = __wrap_malloc(2);
  __wrap_free(p);
}

void child()
{
  printf("=== %d ===\n", getpid());
  void *p = __wrap_malloc(1);
  __wrap_free(p);
  printf("=== %d end ===\n", getpid());
}

void parent(pid_t child)
{
  printf("=== %d ===\n", getpid());
  kill(child, which_signal);
  int status;
  pid_t ret = waitpid(child, &status, 0);
  if (ret == -1) {
    perror("waitpid");
  }
  printf("=== %d end ===\n", getpid());
}

void init_signals()
{
  struct sigaction sa;
  sa.sa_handler = handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (sigaction(which_signal, &sa, NULL) == -1)
    perror("sigaction");
}

int main(int argc, char *argv[])
{
  init_signals();
  pid_t pid = fork();
  if (pid) {
    parent(pid);
    printf("Child did not hang, so I will retry in 1 second.\n");
    sleep(1);
    execl(argv[0], argv[0], NULL);
    return __LINE__;
  }
  child();
  return 0;
}

$ gcc -o test-signal test-signal.c lite-malloc.o && ./test-signal
=== 7522 ===
=== 7521 ===

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions