I have an application which is initiated by the shell and terminated by the shell. Now in my application I had created a fork to reduce the load of my application so currently two processes running on same name with different PID's. Now I want to terminate my program, and if I kill with the PID of my process in shell it only kills the parent process leaving it as a zombie process and the child process remains. So how to kill both child and parent processes through the shell?
See the command killall.
do ps -el you will get the following
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
get pid and ppid of your process do pkill -P <parent_pid_name> meaning your parent process id which has spawned children and followed by kill <signal number> <pid> In this case too, in place of pid you have to give the parent process id who has spawned all the children .
Your father process should trap SIGTERM and kill its child before exit.
I wrote this in C
int child;
void sighandler(int sig) {
if (sig == SIGTERM) {
if (child != -1) kill(child, SIGTERM);
}
}
int main() {
int i;
child = -1;
signal(SIGCHLD, SIG_IGN);
signal(SIGTERM, sighandler);
setsid();
setpgid(0,0);
i = fork();
switch(i) {
case -1:
break;
case 0: // child
sleep (100);
break;
default:
child = i;
sleep (100);
break;
}
return 0;
}
You can kill all processes with the same name with the "killall" command.
pkill command you can use to kill process. Also killall
Related
I try to make a C++ server demo that can restart after passing a SIGHUP signal in the terminal: kill -SIGHUP xx_pid, but it is weird that the SIGHUP signal can only be caught by the parent process. I use fork and exec function to generate the child process, also parent and child process execute the same code. Why my SIGHUP handler failed on the child process? How can I make it work on the child process. (The logic in sighup handler is fork and exec). Here is the code:
void sighup_handler(int signo) {
pid_t pid = fork();
...
execve("./server", argv_cstr.get(), NULL)
}
int main() {
// signal(SIGHUP, sighup_handler);
struct sigaction action;
action.sa_handler = restart_handler;
sigemptyset(&action.sa_mask);
action.sa_flags |= SA_RESTART;
action.sa_flags |= SA_RESETHAND;
if (sigaction(SIGHUP, &action, NULL) < 0) {
LOG(ERROR) << "Fail to register SIGHUP, abort";
abort();
}
while (1) {
std::cout << "a";
usleep(1000 * 4000L);
}
return 0;
}
I run the code in terminal: ./server, its pid is 2899. After I type kill -SIGHUP 2899, it generate a child process 39875. But I go on kill -SIGHUP 39875, it doesn't work. Why? The child process also execute the whole codes, include the signal(SIGHUP, restart_handler); in the first line of main(), why only the parent process can handle SIGHUP signal?
I am using two forks in my code:
int main()
{
cout<<"Main Process ID is: "<<getpid()<<endl;
int processID;
processID = fork();
cout<<"Part 1"<<endl;
cout<<"PID is: "<<getpid()<<" Child PID: "<<processID<<" Parent PID: "<<getppid()<<endl;
processID = fork();
cout<<"Part 2"<<endl;
cout<<"PID is: "<<getpid()<<" Child PID: "<<processID<<" Parent PID: "<<getppid()<<endl;
return 0;
}
But there are some strange "Parent ID" for "children". Why? (Please refer to screenshot below)
Thanks a lot in advance.
In your case the parent executed first, hence got eventually terminated. In this case child become orphan and hence it's parent id got replaced with the id of other process in same group or the child got re-parented.Hence, the parent id is different(strange).
I fork a child process which in turn spawns a grand-child process and returns. If there are any errors in spawning that grand-child, the child writes to stderr using fprintf statements and exits.
I am trying to read stderr from the child process in the parent. But, the parent gets hung in the while loop reading from child process. When I look at ps -ef the child is <defunct>.
Following is the code I wrote to accomplish this. I am new to this and the search on web does not give enough information about why the parent is hung when the child is
int pipe_out[2];
// Create the pipe
if (pipe(pipe_out) < 0) {
perror("Failed pipe");
exit(1);
}
// Create the child process
int status;
pid_t pid = fork();
switch(pid) {
case -1:
perror("Failed fork");
exit(1);
case 0: { // Child
close(pipe_out[0]); // close read end
// Make stderr go to pipe write end
dup2(pipe_out[1], STDERR_FILENO);
close(pipe_out[1]);
// start my process
execvp(inp_args[0], inp_args);
_exit(EXIT_FAILURE);
break;
}
default: { // Parent
close(pipe_out[1]); // close write end
// read from child
while( read(pipe_out[0], buffer, sizeof(buffer)) )
log(stdout, "%s\n",buffer);
}
// wait for end then close other end of pipe
waitpid(pid, &status, 0);
if (WIFSIGNALED(status))
log(stdout, "killed by signal %d\n", WTERMSIG(status));
close(pipe_out[0]);
}
}
I been reading a countless time on stackoverflow that to determine if a process is running, one should use kill(pid,0) but I cant make it work
here is my code, , it cannot detect when the child process has been killed and I dont understand why
(sorry for the ident, but hte code escaping on stackoverflow is just a pain for long pieces of codes)
#include <sys/signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main()
{
int pid = fork();
if (pid < 0)
{
printf("Forking failed\n");
}
else if (pid == 0) // child process
{
do
{
printf("child process\n");
sleep(1);
}while(1);
//execvp("ls", NULL); //launches the application
}
else //parent process
{
printf("parent process\n");
for(int i=0;i<10;i++)
{
if(i==5)
kill(pid,SIGTERM); //kills the child process
if(kill(pid, 0) == 0)
printf("process child %d is runnig\n",pid);
else if(kill(pid, 0) == -1)
{
switch(errno)
{
case ESRCH: printf("process child %d is not runnig\n",pid); break;
case EPERM: printf("process child %d cannot be killed\n",pid); break;
default: printf("%s\n",strerror(errno)); break;
}
}
sleep(1);
}
}
}
here is the output
parent process
process child 1918 is runnig
child process
process child 1918 is runnig
child process
process child 1918 is runnig
child process
process child 1918 is runnig
child process
process child 1918 is runnig
child process
process child 1918 is runnig
process child 1918 is runnig
process child 1918 is runnig
process child 1918 is runnig
process child 1918 is runnig
Until the killed child process gets reaped by wait(), its PID is still valid, and kill(pid, 0); will succeed, since the PID exists. Your code attempts to kill() the child process, but fails to wait() for it.
Note that even in the best case, kill(pid, 0); is not reliable. With only 32766 different PIDs, it doesn't take long before process IDs get recycled.
alright I finaly figured it out
kill(pid,SIGTERM); //kills the child process
do
{
pid = waitpid(-1, NULL, WNOHANG);
if(pid == 0)
sleep(1);
}while(pid<=0);
I use posix_spawnp to spawn child processes from my main process.
int iRet = posix_spawnp(&iPID, zPath, NULL, NULL, argv, environ);
if (iRet != 0)
{
return false;
}
Sometimes, after a child process is spawned without errors, it suddenly becomes defunct. How could this occur?
I use a signal handler to reap child processes:
void SigCatcher(int n)
{
while(waitpid( -1, NULL, WNOHANG ) > 0);
}
and I manually call it whenever I kill a child process.
kill(oProcID, SIGKILL);
signal (SIGCHLD, SigCatcher);
Could this cause spawned children to go defunct (without me calling kill)?
This:
kill(oProcID, SIGKILL);
signal (SIGCHLD, SigCatcher);
looks like a race condition. You need to install the signal handler before killing the child process, otherwise you risk missing the signal.
Have you called:
signal(SIGCHLD, SigCatcher);
anywhere else?
If you haven't, then you need to do so before any child processes are even spawned to ensure that those children are reaped when they terminate.
As Unwind points out, your current calls to kill and signal are the wrong way around.
Typical use would be:
signal(SIGCHLD, handler);
posix_spawnp(...);
...
// do other stuff
...
kill(pid, SIGKILL);