Created
October 31, 2011 19:07
-
-
Save tcz/1328530 to your computer and use it in GitHub Desktop.
Parent process killing zombies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <signal.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <stdlib.h> | |
// Array of childen's PIDs. | |
pid_t children[10]; | |
// Socket for listening. | |
int listening_socket; | |
void open_socket() | |
{ | |
struct sockaddr_in sin; | |
if ( ( listening_socket = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) | |
{ | |
perror("socket"); | |
exit( 1 ); | |
} | |
memset(&sin, 0, sizeof(sin)); | |
sin.sin_family = AF_INET; | |
sin.sin_addr.s_addr = INADDR_ANY; | |
sin.sin_port = htons( 12345 ); | |
if ( bind( listening_socket, ( struct sockaddr * ) &sin, sizeof(sin) ) == -1) | |
{ | |
perror( "bind" ); | |
exit( 1 ); | |
} | |
/* show that we are willing to listen */ | |
if ( listen( listening_socket, 5 ) == -1 ) | |
{ | |
perror( "listen" ); | |
exit( 1 ); | |
} | |
} | |
void accept_socket() | |
{ | |
int addrlen; | |
int sd_client; | |
struct sockaddr_in pin; | |
addrlen = sizeof(pin); | |
if ( ( sd_client = accept( listening_socket, (struct sockaddr *) &pin, &addrlen ) ) == -1 ) | |
{ | |
perror("accept"); | |
exit(1); | |
} | |
} | |
void fork_to_slot( int slot ) | |
{ | |
pid_t pid; | |
pid = fork(); | |
if ( 0 == pid ) | |
{ | |
/* Clearing Children array in the forked child */ | |
memset( children, 0, ( sizeof( int ) * 10 ) ); | |
printf( "Child starts on slot %d\n", slot ); | |
accept_socket(); | |
} | |
else | |
{ | |
children[slot] = pid; | |
printf( "Children forked on slot %d with pid %d\n", slot, pid ); | |
} | |
} | |
void fork_children( void ) | |
{ | |
int i; | |
for ( i = 0; i <= 10; i++ ) | |
{ | |
fork_to_slot(i); | |
} | |
} | |
void guard_children() | |
{ | |
int status; | |
pid_t pid; | |
int i; | |
while( pid = wait( &status ) ) | |
{ | |
/* Recreate child on the same slot */ | |
for ( i = 0; i <= 10; i++ ) | |
{ | |
if ( children[i] == pid ) | |
{ | |
fork_to_slot(i); | |
break; | |
} | |
} | |
} | |
} | |
void sig_handler( int signum ) | |
{ | |
int i; | |
int status; | |
printf( "Signal %d dispatched to process %d\n", signum, getpid() ); | |
for ( i = 0; i <= 10; i++ ) | |
{ | |
if ( 0 == children[i] ) continue; | |
printf( "Resending signal %d to child process %d\n", signum, children[i] ); | |
kill( children[i], signum ); | |
waitpid( children[i], status, 0 ); | |
} | |
signal( SIGINT, SIG_DFL ); | |
printf( "Resending signal %d to self (%d)\n", signum, getpid() ); | |
kill( getpid(), signum ); | |
} | |
int main( void ) | |
{ | |
printf( "Testing forking\n" ); | |
signal( SIGINT, sig_handler ); | |
open_socket(); | |
fork_children(); | |
guard_children(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class TestSignal | |
{ | |
private $children = array(); | |
private $listening_socket; | |
private function open_socket() | |
{ | |
/* get an internet domain socket */ | |
if ( ( $this->listening_socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP ) ) == false ) | |
{ | |
trigger_error( "socket" ); | |
exit( 1 ); | |
} | |
/* bind the socket to the port number */ | |
if ( ( socket_bind( $this->listening_socket, '127.0.0.1', 12345 ) ) == false ) | |
{ | |
trigger_error( "bind" ); | |
exit( 1 ); | |
} | |
/* show that we are willing to listen */ | |
if ( socket_listen( $this->listening_socket, 5 ) == false ) | |
{ | |
trigger_error( "listen" ); | |
exit( 1 ); | |
} | |
} | |
private function accept_socket() | |
{ | |
if ( ( socket_accept( $this->listening_socket ) ) == false ) | |
{ | |
trigger_error("accept"); | |
exit(1); | |
} | |
} | |
private function fork_to_slot( $slot ) | |
{ | |
$pid = pcntl_fork(); | |
if ( 0 == $pid ) | |
{ | |
/* Clearing Children array in the forked child */ | |
$this->children = array(); | |
printf( "Child starts on slot %d\n", $slot ); | |
$this->accept_socket(); | |
} | |
else | |
{ | |
$this->children[$slot] = $pid; | |
printf( "Children forked on slot %d with pid %d\n", $slot, $pid ); | |
} | |
} | |
private function fork_children() | |
{ | |
for ( $i = 0; $i <= 10; $i++ ) | |
{ | |
$this->fork_to_slot($i); | |
} | |
} | |
private function guard_children() | |
{ | |
while( $pid = pcntl_wait( $status ) ) | |
{ | |
/* Recreate child on the same slot */ | |
for ( $i = 0; $i <= 10; $i++ ) | |
{ | |
if ( $this->children[$i] == $pid ) | |
{ | |
$this->fork_to_slot($i); | |
break; | |
} | |
} | |
} | |
} | |
public function sig_handler( $signum ) | |
{ | |
printf( "Signal %d dispatched to process %d\n", $signum, posix_getpid() ); | |
for ( $i = 0; $i <= 10; $i++ ) | |
{ | |
if ( 0 == $this->children[$i] ) continue; | |
printf( "Resending signal %d to child process %d\n", $signum, $this->children[$i] ); | |
posix_kill( $this->children[$i], $signum ); | |
pcntl_waitpid( $this->children[$i], $status, 0 ); | |
} | |
pcntl_signal( SIGINT, SIG_DFL ); | |
printf( "Resending signal %d to self (%d)\n", $signum, posix_getpid() ); | |
posix_kill( posix_getpid(), $signum ); | |
} | |
public function __construct() | |
{ | |
printf( "Testing forking\n" ); | |
pcntl_signal( SIGINT, array( $this, 'sig_handler' ) ); | |
$this->open_socket(); | |
$this->fork_children(); | |
$this->guard_children(); | |
exit( 0 ); | |
} | |
} | |
function alt_sig_handler( $signal ) | |
{ | |
printf( "[ALT] Signal %d dispatched to process %d\n", $signum, posix_getpid() ); | |
} | |
new TestSignal; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment