Solved

How to clean up a C program when terminated??

Posted on 2004-04-29
9
267 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
  • 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
 
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

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…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

707 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now