Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/articles/c-tutorials/)
-   -   Ways to Terminate or Kill Process (http://www.go4expert.com/articles/terminate-kill-process-t27110/)

poornaMoksha 8Nov2011 13:56

Ways to Terminate or Kill Process
 
A running instance of a program executable is known as a Process. A process when run can do various things like open some files, read/write some data, create some threads/processes, register some functions as callback in various scenarios etc. According to the logic, after the completion of the desired work, the process terminates. In this article we will focus over how a process terminates.

The focus here will be processes whose code is written in C and are running on Linux platform.

Process Termination



Since this article revolves around Linux processes written in 'C' , so there are eight ways for a process to terminate :
  1. Return from main()
  2. Call exit() function
  3. Call _exit() or _Exit() function
  4. Return of last thread from its triggering function
  5. Calling pthread_exit() function from the last thread
  6. Calling abort() function
  7. When a signal is received
  8. Response of last thread to a cancellation request.

Lets understand all these ways one by one :

1) Return from main()



Well, this is the most common way of exiting from a process. Usually we do a return from main() whenever we want our process to terminate. Following is a piece of code explaining this :

Code:

#include<stdio.h>
 
 int main(void)
 {
    printf("\n Hello World\n");
    return 0;
 }

In the above piece of code we see that we return from main() after we are done with the printf() call.

2) Call exit(int status) function



This is another common way that you must have seen in various functions. The difference being that while in a function other than main(), through 'return' one can terminate the current function and return to the caller function while through exit() we can terminate the process. Being used from main() both return and exit() have same effect ie the process is terminated. Lets understand it through an example code :

Code:

#include<stdio.h>
 
 int func(void)
 {
    printf("\n Inside func()\n");
    return 0;
 }
 
 int main(void)
 {
    printf("\n Hello World\n");
    func();
    printf("\n returning from main()\n");
 
    return 0;
 }

The output of the above code is :

Code:

~/practice $ ./helloWorld 
 
  Hello World
 
  Inside func()
 
  returning from main()

We see that the function func() is executed and then the code flow returns to main() and then the rest of the main() function is executed.

Now, lets see another example :

Code:

#include<stdio.h>
 #include<stdlib.h>
 
 void func(void)
 {
    printf("\n Inside func()\n");
    exit(0);
 }
 
 int main(void)
 {
    printf("\n Hello World\n");
    func();
    printf("\n returning from main()\n");
 
    return 0;
 }

The output of the above code comes out to be :

Code:

~/practice $ ./helloWorld 
 
  Hello World
 
  Inside func()

So its clearly visible through the output that after the exit() function is executed, the process gets terminated and the rest of the caller function (main() function) is not executed.

Note : In this example, I have changed the signature of the function func() so as to avoid the warning from compiler as now we are not returning anything from function func().

3) Call _exit(int status) or _Exit(int status) function



To begin with, lets clear the difference between the two. The major difference being that _Exit are specified by ISO C, whereas _exit is specified by POSIX.1. Otherwise both the functions perform the same operation. From the man page of _exit/_Exit we have :

Quote:

The function _exit() terminates the calling process "immediately". Any open file descriptors belonging to the process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent a SIGCHLD signal.

The value status is returned to the parent process as the process's exit status, and can be collected using one of the wait(2) family of calls.

The function _Exit() is equivalent to _exit(). The function _exit() does not call any functions registered with atexit
Things are pretty much clear up till this point but what does that last line in the above quote from man page signify. Well this signifies one of the major differences between exit() function (explained in point 2 above) and the _exit/_Exit functions.

Lets understand what does atexit() function do ?

Well, 'atexit(void (*function)(void))' function registers a function that is called when the process terminates. It could be a clean up function for all the memory allocations done or simply could be used for any other work. If more that one functions are registered using atexit() function, then they are called in order from the last registered function to the first registered function.

Lets understand this difference between exit() and _exit/_Exit functions using an example :

Code:

#include<stdio.h>
 #include<stdlib.h>
 //#include<unistd.h>
 
 void exit_func1(void);
 void exit_func2(void);
 
 int main(void)
 {
    printf("\n Inside main() \n");
 
    if(0 != atexit(exit_func1))
    {
        printf("\n atexit() failed\n");
    }
 
    if(0 != atexit(exit_func2))
    {
        printf("\n atexit() failed\n");
    }
 
    printf("\n exiting main() \n");
 
    exit(0);
 
    return 0;
 }
 
 void exit_func1(void)
 {
    printf("\n exit_func1() called \n");
 }
 
 void exit_func2(void)
 {
    printf("\n exit_func2() called \n");
 }

we see that in the above program, to functions are registered through atexit() function and the process being terminated through a call to exit(0) in the main() function.

Lets see the output of this program :

Code:

~/practice $ ./exit
 
  Inside main() 
 
  exiting main() 
 
  exit_func2() called 
 
  exit_func1() called

So, we see that after the last print statement from the main() function the registered function get called in the order as described above.

Now, lets use the _exit() function instead of exit() function and see what happens. Here is the code :

Code:

#include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h>
 
 void exit_func1(void);
 void exit_func2(void);
 
 int main(void)
 {
    printf("\n Inside main() \n");
 
    if(0 != atexit(exit_func1))
    {
        printf("\n atexit() failed\n");
    }
 
    if(0 != atexit(exit_func2))
    {
        printf("\n atexit() failed\n");
    }
 
    printf("\n exiting main() \n");
 
    _exit(0);
 
    return 0;
 }
 
 void exit_func1(void)
 {
    printf("\n exit_func1() called \n");
 }
 
 void exit_func2(void)
 {
    printf("\n exit_func2() called \n");
 }

Now, lets see the output :

Code:

~/practice $ ./exit
 
  Inside main() 
 
  exiting main()

So, its clear now looking at the output that once we used _exit() function, the registered functions through atexit() are not called and the control is directly transfered to the caller of main() function.

4) Return of last thread from its triggering function



Well, the last thread in any program is the thread in which main() runs. So its very obvious that when this thread returns, the process will terminate.

5) Calling pthread_exit() function from the last thread



Again, continuing from the explanation of point 4 above, the last thread is the thread in which main() runs, so calling pthread_exit() from this thread will terminate the thread in which main() is running and hence the process will terminate.

6) Calling abort() function



This is a special function causes abnormal termination of the process. It does this by first unblocking the SIGABRT signal and then issues this signal to the process from which it is called. The process is terminated unless this signal is called and the signal handler does not return(this could be achieved using longjmp() function).

7) When a signal is received



Yes, when a signal is received by a process which is not handling this type of signal, the process terminates. Consider what happens when you press ctrl+c on a running process. This user activity generates a SIGINT signal to the process. If the process is not handling this type of signal, the process terminates. Lets look at an example to understand this :

Code:

#include<stdio.h>
 
 int main(void)
 {
    while(1)  // Simulate a dummy wait
        sleep(1);
 
    return 0;
 }

The above code does nothing, it just waits infinitely, which gives us ample time so that we can issue ctrl+c. When I run the above program, and issue ctrl+c , this is what I get :

Code:

~/practice $ ./small_signal 
 ^C
 ~/practice

So, looking at the output, we see that the process got terminated.

Now, lets handle the signal generated by ctrl+c, here is the code :

Code:

#include<stdio.h>
 #include<signal.h>
 #include<unistd.h>
 
 void sig_handler(int signo)
 {
    if (signo == SIGINT)
        printf("received SIGUSR1\n");
    else
        printf("ERR : received signal %d\n", signo);
 }
 
 
 int main(void)
 {
    if (signal(SIGINT, sig_handler) == SIG_ERR)
        printf("\ncan't catch SIGUSR1\n");
    while(1)  // Simulate a dummy wait
        sleep(1);
 
    return 0;
 }

In the above code, I used signal handling (http://www.go4expert.com/showthread.php?t=26840) to handle the signal generated from ctrl+c. Lets see the output :

Code:

~/practice $ ./small_signal 
 ^Creceived SIGUSR1
 ^Creceived SIGUSR1
 ^Creceived SIGUSR1
 Killed

So, from the output above, I ran the program and tried ctrl+c multiple time but could not terminate the program as the program now is handling the signal generated by ctrl+c. So, finally I had to issue the 'killall -9 small_signal' command from some other terminal to terminate the program.

8) Response of last thread to a cancellation request.



Well, if somehow we cancel the last thread (as explained in above points, the last thread is the thread in which main() function runs) surely the process will terminate. This can be achieved using the pthread_cancel() function of the pthread library.

A point worth noting



So, now we have understood almost all the ways to terminate a process, but did you think over the 'status' variable used in return statement or exit(), _exit() and _Exit() functions. Why do we need to pass this status? What do we gain from it?

Well, it is used to provide the exit status of the process. This exit status would determine whether the process completed successfully or it failed.

On a command line, the exit status is fetched by command :

Quote:

echo $?
Lets take a small example to understand this :

Code:

#include<stdio.h>
 
 int main(void)
 {
    printf("\n Hello World\n");
 
    return 0;
 }

When I run the following program and check the exit status, i see :

Code:

~/practice $ ./helloWorld 
 
  Hello World
  ~/practice $ echo $?
 0

So the exit status is '0' which is same as what we returned in code.

Now lets change the return value and re confirm :

Code:

#include<stdio.h>
 
 int main(void)
 {
    printf("\n Hello World\n");
 
    return 2;
 }

The output :

Code:

~/practice $ ./helloWorld 
 
  Hello World
 ~/practice $ echo $?
 2

So we see that once we changed the return value to '2', the exit status also becomes '2'.

On a final note, the standard is that the return value '0' is used for success while any other value signifies failure.

Conclusion



To conclude, in this article, we studied different ways in which a program can terminate and how it behaves while termination.

Stay tuned for more...

archanababu 22Nov2011 14:29

Re: Ways to Terminate or Kill Process
 
By reading ur article i got really helpful information about kill or terminate a process. Also got information about process and what the process is. Thanks dear!!

poornaMoksha 23Nov2011 11:40

Re: Ways to Terminate or Kill Process
 
Quote:

Originally Posted by archanababu (Post 89441)
By reading ur article i got really helpful information about kill or terminate a process. Also got information about process and what the process is. Thanks dear!!

You are always welcome buddy!!!!

globlesearching 7Dec2011 12:50

Re: Ways to Terminate or Kill Process
 
Information is very informative i like this post. And I share to my all facebook friends...Keep submit more...

Thanks for...

poornaMoksha 7Dec2011 14:02

Re: Ways to Terminate or Kill Process
 
Quote:

Originally Posted by globlesearching (Post 89894)
Information is very informative i like this post. And I share to my all facebook friends...Keep submit more...

Thanks for...

Thanks, I regularly post articles here. Keep yourself updated!!!!!!

Scripting 14Dec2011 22:08

Re: Ways to Terminate or Kill Process
 
Nice tut man, good work done, but what about the way TerminateProcess(GetCurrentProcess(),0);

I know it's pretty brute-force way, but still a way :D

sura 18Dec2011 21:17

Re: Ways to Terminate or Kill Process
 
Nice and Informative . . . . .
Thanks.

poornaMoksha 21Dec2011 15:24

Re: Ways to Terminate or Kill Process
 
Quote:

Originally Posted by Scripting (Post 90286)
Nice tut man, good work done, but what about the way TerminateProcess(GetCurrentProcess(),0);

I know it's pretty brute-force way, but still a way :D

I think that this function is for windows.
I already specified in my article: The focus here will be processes whose code is written in C and are running on Linux platform.

Scripting 23Dec2011 19:59

Re: Ways to Terminate or Kill Process
 
Quote:

Originally Posted by poornaMoksha (Post 90442)
I think that this function is for windows.
I already specified in my article: The focus here will be processes whose code is written in C and are running on Linux platform.

I'm not sure whether it's only for Windows, but maybe yes ... I didn't noticed that line, sorry, my bad. :)


All times are GMT +5.5. The time now is 06:37.