-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
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
Labels
No labels