Solved

How to clean up a C program when terminated??

Posted on 2004-04-29
9
280 Views
Last Modified: 2010-04-22
Hi there...

I am writing a C program on linux which I want to terminate gracefully. That is, I want to be able to close all running threads that may be active at the time the user does Ctrl C. My program listens for socket conenctions and create serperate threads to handle the connections it receives and do some processing while the main thread continues to listen for connections. How do I terminate all the threads, close all sockets..etc when the user ends the program either by closing the console or by pressing Ctrl C or Z?

engin32us
0
Comment
Question by:engin32us
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
9 Comments
 
LVL 12

Expert Comment

by:stefan73
ID: 10956889
Hi engin32us,
Actually, you don't need to. All open files and sockets are closed when a process terminates. But yes, it is a good practice.

For your graceful termination you need signal handling. A CTRL-C is a SIGINT, and closing a terminal sends a SIGHUP to your process.

Check man signal and man 6 signal for details. I'll give you a simple example.

Cheers,
Stefan
0
 
LVL 12

Assisted Solution

by:stefan73
stefan73 earned 150 total points
ID: 10956915
engin32us,

Here you go:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static void sighandler(int sig){
      printf("Caught signal %d, resetting signal handler\n",sig);
      signal(sig,sighandler);
}

int main(){
      /* Setup signal handler */
      signal(SIGHUP,sighandler);
      signal(SIGINT,sighandler);
      signal(SIGTERM,sighandler);

      /* sleep() is interrupted by a signal, so we loop here */
      while(1) {
            sleep(999);
            printf("Sleep woke up.\n");
      }
}

      

(you'll need to kill it with -9, as it's also capturing SIGTERM)

For a more complex application with multiple threads, it's usually best not to close them instantly, but to use a shutdown flag which is monitored regularly:

int shutdown=0;

[...]
while(!shutdown){
    do_something();
}

...your signal handler will set shutdown, so all threads shut down gracefully.

Stefan
0
 
LVL 45

Expert Comment

by:sunnycoder
ID: 10957351
Hi engin32us,

The approach is the same as what stefan recommended ... catch the signal ...

However, I highly recommend that you use sigaction() interface instead of signal() interface ... Sigaction is lot more powerful, flexible and less error prone as compared to singal()

man sigaction

>How do I terminate all the threads, close all sockets..etc
to kill the threads use pthread_kill ()

man pthread_kill

You will have all the socket ids in the main thread (it accepts the connections) ... You need to maintain a list of them (the active/open sockets) and during cleanup you can traverse that list and close all the open sockets ...

Alternatively you can register all the cleanup activity using the atexit() function

man atexit

The functions registered using atexit() will be called when the process is about to exit so you save the signal handling efforts ... However signal handling is more graceful and offers you better control

If you need more information, post back :o)


cheers
sunnycoder
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:stefan73
ID: 10958463
sunnycoder,
> use sigaction() interface instead of signal() interface

Good point. I guess I was too lazy for using sigaction() :-)

Stefan
0
 
LVL 4

Expert Comment

by:oumer
ID: 10959753
I have had several problems when using signals and threads. The best way I found is to just exit with the signal handler and do my cleanup with some function that I had registed at the beginning of my code. Also, I will mask the signal from all the threads except the one that I want to catch the signal, cause sometimes that also causes a problem. Example program will follow in a momment ......
0
 
LVL 4

Accepted Solution

by:
oumer earned 100 total points
ID: 10959922
The skeleton code of how I would do is like this ....



bool exited = false;

void bye()
{
//I use the exited variable, cause I have sometimes encounterd bye being called more than once incase I press ctrl+c again while we are in bye

   if(!exited)
      exited=true;
   else
       return;

  //do you cleanup of threads and objects here

}

void signal_handler( int sig)
{
   printf("hmm, you don't like me anymore?\n");
   exit(0);  //atexit will be called at this point
}

void * thread_1(void *arg)
{
//thread_1's body

}

void * thread_2(void *arg)
{
//thread_1's body

}

int main()
{
sigset_t set;
struct sigaction sa;

atexit(bye);

//These three lines will mask the SIGINT from being catched by the child threads
sigemptyset(&set);
sigaddset(&set,SIGINT);
pthread_sigmask(SIG_BLOCK, &set, NULL);

pthread_create(&th1, NULL, thread_1, NULL);
pthread_create(&th2, NULL, thread_2, NULL);

//now the threads are created, you can unmask the SIGINT now, making sure only the parent thread wil catch the signal
pthread_sigmask(SIG_BLOCK, &set, NULL);
sa.sa_handler=signal_handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);

//here you can wait for the two threads to finsih or do whatever you want to do
//just make sure you do something so that control doesn't reach to the end of the main function ....

}
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10976907
oumer,
I wonder how Linux does the signal handling within a multi-threaded process when each thread has his own pid...

Any ideas?

Stefan
0
 
LVL 4

Expert Comment

by:oumer
ID: 10977046
Hi Stefan,
>I wonder how Linux does the signal handling within a multi-threaded process when each thread has his own pid...
I dont get it when you say "when each thread has his own pid ..."
0
 
LVL 4

Expert Comment

by:oumer
ID: 10977141
Let's say you have a signal handler for some signals like SIG_FPE, SIG_SEGV, and SIG_INT

In the case of floating point ad segmentaion errors, the signals are sent to the concerned thread, the one that has caused the exception to happen. So if the signal handler was shared between the threads (i.e. you didn't mask the signals), it will be called from the concerned thread.

On the case asynchronous signals like sig_int when you press ctrl+c, there is no guarantee from which thread the signal handler will be called.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Boot Linux vm into a menu system 2 102
Prestashop 1.5 Redirect Problem 1 129
incorrect file reading in bash 7 151
linux 13 147
Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question