Preface: I used wait() and the non-blocking model before recycling the child process. After learning the signal today, the recycling mechanism can be improved to a higher level. Through the signal function, the parent process only needs to do its own thing, and it will be triggered after receiving the signal. signal function.
Possible bugs in signal handlers:
1. The stop signal will also trigger the SIGCHLD signal, causing wait to block;
2. After stopping, the signal will also be triggered, causing the parent process to block;
3. Calling sigaction(), artificially sending a SIGCHLD signal will also block the parent process;
4. Multiple processes end at the same time, which may cause incomplete recovery and generate zombie processes (the same signal is not queued);
The final code for the solution:
//Recycle subprocess asynchronously
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#define NR 40
/*
* Bugs: If multiple processes end at the same time, it may cause incomplete recycling and generate zombie processes (the same kind of signal is not queued)
* The circular method waitpid solves the above bugs
*/
void waitChild(int signo)
{
pid_t pid;
printf("a sig recv:% d\n",signo);
if(signo!=SIGCHLD) return;
while(1) //Guaranteed to trigger a signal once and recycle all terminated child processes
{
pid=waitpid(-1,NULL,WNOHANG|WUNTRACED);/ /Guaranteed non-blocking, and stop does not trigger the signal
printf("wait child:%d\n",pid);
if(pid==0||pid==-1)
break;
}
}
int main(void)
{
pid_t pid;
#if 0
//The child process ends or stops or SIGCHLD signal occurs from stop to continue
if(signal(SIGCHLD,waitChild)==SIG_ERR)
{
perror("signal");
return 2;
}
#else
struct sigaction ac={.sa_handler=waitChild};//Handler function
sigemptyset(&ac.sa_mask);//Do not expect to mask other signals
ac.sa_flags=SA_NOCLDSTOP;//The SIGCHLD signal does not occur when the process stops
sigaction(SIGCHLD,&ac,NULL) ;
#endif //
int i;
for(i=0;i<NR;i++)
{
pid=fork();
if(pid==-1) return 1;//error
else if(pid==0)/ /child
{
printf("%dth child <%d> start work.\n",i,getpid());
sleep(3);
printf("%dth child <%d> end work.\n",i,getpid());
exit(0);
}
}
//parent
while(1)
{
getchar();
printf("parent working....\n");
}
return 0;
}