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