Child process has changed state. This signal is raised whenever a child process receives a signal or terminates. This can be used to call wait4(2) to cleanup any ZombieProcesses that the process may have. On some Unixes it is possible to explicitly set SIGCHLD to "SIG_IGN" (ignore) and child processes will be cleaned up automatically. The default action (SIG_DFL) for this signal is to ignore it (but this does not reap the process until the parent wait()s).
In perl, you would do one of the following:
1. wait till child finishes
if (fork()==0) { # ==0 implies child process do stuff... exit; } # if fork returned -1, there was an error forking (but we'll ignore that) # if here, assume it is the parent processes # wait() call won't return until the child process has finished. wait(); # when this returns, the child has been "reaped" # could use waitpid() with WNOHANG to return -1 if child isn't finished yet # when here, the child process has finished. ...
2. Don't care about the child process finishing
$SIG{CHLD}='IGNORE'; # see the perlipc(1) man page for this... if (fork()==0) { do child stuff... exit; } continue in parent....
If you don't do either of wait() or set the signal handler, then the child will remain a ZombieProcess.
Interesting note for RedHat enterprise Linux 4 and Fedora 4 users, found with both gcc 3.4.4 (RHEL4) and gcc 4.0.0 (Fedora4): another issue found when ignoring SIGCHLD is that the system() function will not work in your child code. If you ignore SIGCHLD, all of your calls to system() will return -1, indicating that they fail, even though they are actually completed OK. Using this test code:
pid_t nPid; signal( SIGCHLD, SIG_IGN ); if( 0 == ( nPid = fork() ) ) { ofstream ofstrTestFile; ofstrTestFile.open( "TestFile.txt", ofstream::out | ofstream::trunc ); ofstrTestFile << "Testing...1...2...3...4..." << ends; ofstrTestFile.close(); string strTemp; strTemp = "mv TestFile.txt TestFile.mv"; int nTemp; nTemp = system( strTemp.c_str() ); if ( 0 != nTemp ) { cout << "It failed nTemp <" << nTemp << ">" << endl << endl; } else { cout << "It worked nTemp <" << nTemp << ">" << endl << endl; } return ( true ); }
It will fail and return -1. If you remove signal( SIGCHLD, SIG_IGN ); the code will work properly. In either case, the mv command is actually performed successfully.
This used to work with the signal call in older versions of Redhat and older compilers.
8 pages link to SIGCHLD: