Re: solid lockup on 2.1.86 under heavy signal activity

Dean Gaudet (dgaudet-list-linux-kernel@arctic.org)
Wed, 25 Feb 1998 03:04:21 -0800 (PST)


I figure folks may be more likely to investigate this if they have a small
test program that can reproduce the lockup. So here's one that mimics
some of the behaviour of Apache when you continuously send it SIGUSR1.
It's just fork()s, sigaction()s, and kill()s, pretty simple.

On a dual cpu box running 2.1.86 this will lock solid. Nope it won't
happen on a single CPU box.

Dean

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>

#define N_CHILD 10

int usr1;

void usr1_handler(int sig)
{
usr1 = 1;
}

int fork_a_child(void)
{
pid_t c;
struct sigaction sa;

c = fork();
if (c == -1) {
perror("fork child");
kill(-getpgrp(), SIGTERM);
exit(1);
}
if (c) {
return c;
}

/* otherwise we're pretending to be an apache child process */
/* we have to do at least one SIGUSR1 manipulation */

sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = usr1_handler;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("child sigaction(SIGUSR1)");
exit(1);
}

while(1) {
pause();
if (usr1) {
break;
}
}
exit(0);
}

/* we pretend to be apache's parent process */
void first_child(void)
{
struct sigaction sa;
int i;
pid_t children[N_CHILD];
pid_t c;

if (setsid() == -1) {
perror("setsid");
exit(1);
}

sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = usr1_handler;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("first sigaction(SIGUSR1)");
exit(1);
}

/* spawn the first generation of children */
for (i = 0; i < N_CHILD; ++i) {
children[i] = fork_a_child();
}
while(1) {
c = waitpid(-1, NULL, 0);
if (c > 0) {
for (i = 0; i < N_CHILD; ++i) {
if (children[i] == c) {
/* replace it right away */
children[i] = fork_a_child();
break;
}
}
if (i == N_CHILD) {
fprintf(stderr, "bogus pid: %d, dying\n", c);
kill(-getpgrp(), SIGTERM);
exit(1);
}
}
else if (usr1) {
putchar('.');
fflush(stdout);
kill(-getpgrp(), SIGUSR1);
}
}
}

void main(void)
{
pid_t c;

c = fork();
if (c == -1) {
perror("fork first_child");
exit(1);
}
if (c == 0) {
first_child();
exit(0);
}
/* give it a moment to set up */
sleep(1);
/* attack! */
while(1) {
if (kill(c, SIGUSR1) == -1) {
perror("kill(c, SIGUSR1)");
kill(-c, SIGTERM);
exit(1);
}
}
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu