Skip to content

Instantly share code, notes, and snippets.

@tcz
Created October 31, 2011 19:07
Show Gist options
  • Save tcz/1328530 to your computer and use it in GitHub Desktop.
Save tcz/1328530 to your computer and use it in GitHub Desktop.
Parent process killing zombies
#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;
}
<?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