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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions