I want to fully terminate a process on Linux C89.
The flow is: check if its already dead, if not, let it die peacefully using sigterm
and wait 10 seconds till it dies. If its still alive - SIGKILL
it.
int TerminateProcessIMP(pid_t process_to_kill)
{
assert(process_to_kill);
/*---------------------------------------------------------*/
/* check if process is already does not exist */
if (!IsProcessAliveIMP(process_to_kill))
{
return (SUCCESS);
}
/*---------------------------------------------------------*/
/* terminate process_to_kill */
if (kill(process_to_kill, SIGTERM))
{
fprintf(stderr, "%s\n", strerror(errno));
}
if (!IsProcessAliveIMP(process_to_kill))
{
return (SUCCESS);
}
/*---------------------------------------------------------*/
/* if its still alive, SIGKILL it */
if (kill(process_to_kill, SIGKILL))
{
fprintf(stderr, "%s\n", strerror(errno));
}
if (!IsProcessAliveIMP(process_to_kill))
{
return (SUCCESS);
}
/*---------------------------------------------------------*/
return (FAILURE);
}
/******************************************************************************/
int IsProcessAliveIMP(pid_t process_to_check)
{
time_t start_time = 0;
time_t end_time = 0;
time_t time_to_wait = 10; /* in seconds */
assert(process_to_check);
start_time = time(0);
end_time = start_time + time_to_wait;
/* give it time to be terminated because maybe it frees memory meanwhile */
while (0 != kill(process_to_check, 0) && time(0) < end_time)
{}
/* check if it still exists */
if (0 == kill(process_to_check, 0))
{
return (0);
}
/* the process is still alive */
return (1);
}
What do you think?
Right now, it does not work and does not terminate the process.
It tries to terminate the process but fails to do that. I can't figure out why.
Thanks.
You're doing unnecessary things.
To check if a process exists:
kill(pid, 0);
If the return value is 0, then the process exists, if -1 then you have to check errno
. In case of ESRCH
:
The target process or process group does not exist. Note that an existing process might be a zombie, a process that has terminated execution, but has not yet been wait(2)ed for.
To terminate a process:
kill(pid, SIGTERM); // signal can be blocked, handled or ignored
or
kill(pid, SIGKILL); // signal cannot be blocked, handled or ignored
After a kill, you have to wait for the process via:
waitpid(pid, &status, 0);
If
status
is notNULL
,wait()
andwaitpid()
store status information in theint
to which it points. This integer can be inspected with the macros, described in the man page.
See
Example:
int TerminateProcessIMP(pid_t pid)
{
//check if process exists
int res = kill(pid, 0);
if ((res == -1) && (errno != ESRCH)) {
//error: either EINVAL or EPERM
//ESRCH: an existing process might be a zombie
return -1;
}
if (res == 0) { //process exists
//ask politely to terminate
if (kill(pid, SIGTERM) == -1) {
//error: unable to send a signal to the process
return -1;
}
//let us see if the child complied to our request
res = waitpid(pid, NULL, WNOHANG | WUNTRACED | WCONTINUED);
if (res == -1) {
//most likely not our child (errno == ECHILD)
//but the process could follow our request and still terminate
//if you want to be sure goto SIGKILL below
//or return
} else if (res == 0) {
//our child, but at this point the child has not terminated yet
//(maybe it will never)
//either continue to wait or goto SIGKILL below
} else {
//child complied to our request and terminated in time
//res contains the id of the child (res == pid)
return res;
}
//--- or ---
/* do {
res = waitpid(pid, NULL, WNOHANG | WUNTRACED | WCONTINUED);
//because of WNOHANG
sleep(1);
//your timeout method goes here
} while (!res);
if (res == -1) { //same as above }
if (res > 0) { return res; } */
}
//at this point, the process either does not exists (maybe zombie),
//is not our child or refused our request (SIGTERM)
//send a SIGKILL signal to the process
kill(pid, SIGKILL);
//wait for the process to terminate
res = waitpid(pid, NULL, 0);
/*if (res == -1) {
//not our child, or process does not exists
}*/
/*if (res > 0) {
//child successfully terminated
}*/
return res;
}