I'm using czmq and zmq libraries in my code. I've registered a signal handler for SIGINT by calling signal in main. The code looks like this:
#include "czmq.h"
void sig_int(int signal);
void* pub_handler(){
zctx_t *context = zctx_new ();
void *publisher = zsocket_new (context, ZMQ_PUB);
zsocket_connect (publisher, "tcp://localhost:5555");
sleep(1);
char topic[20] = "REQ: speedlimit";
// while (true)
{
sleep( randof(10) );
zstr_sendm (publisher, topic);
zstr_send (publisher, "driver analysis data");
}
zctx_destroy (&context);
}
void* sub_handler(){
zctx_t *context = zctx_new();
void *subscriber = zsocket_new (context, ZMQ_SUB);
zsocket_connect (subscriber, "tcp://localhost:5557");
srandom ((unsigned) time (NULL));
char subscription [20] = "RESP: speedlimit" ;
zsocket_set_subscribe (subscriber, subscription);
while (true) {
char *topic = zstr_recv (subscriber);
if(!topic)
break;
char *data = zstr_recv (subscriber);
assert (streq (topic, subscription));
puts (topic);
puts (data);
free (topic);
free (data);
}
zctx_destroy (&context);
}
int main(int argc, const char *argv[])
{
pthread_t pub_id, sub_id;
signal (SIGINT, sig_int);
pthread_create(&pub_id, NULL, pub_handler, NULL);
pthread_create(&sub_id, NULL, sub_handler, NULL);
pthread_join(pub_id, NULL);
pthread_join(sub_id, NULL);
return 0;
}
void sig_int(int signal){
printf (" Interrupted\n");
exit(0);
}
compiled as gcc -o app app.c -lpthread -lczmq -lzmq.
The above code doesn't get into signal handler when ctrl+c interrupt is given.
what is the problem with czmq or zmq library and how it should be handled?
The documentation for zctx says that zctx sets up its own signal handler for SIGINT and SIGTERM, probably overriding your signal handler.
Sets up signal (SIGINT and SIGTERM) handling so that blocking calls
such as zmq_recv() and zmq_poll() will return when the user presses
Ctrl-C.
It also says that zctx is deprecated in favor of zsock, which doesn't appear to setup a signal handler according to its documentation. So my first suggestion is to use the new zsock socket API.
However, it seems that in both cases you can also call zsys_handler_set(NULL); (documented here) to explicitly disable the default SIGINT/SIGTERM handling in CZMQ.
PS: printf is not async-signal-safe, meaning that it should not be used in a signal handler. See here for a list of async-signal-safe functions in POSIX.
Got the solution after posting the question in zmq mailing list!!
Pieter Hintjens say's :: CZMQ does set up its own signal handling to trap SIGINT and SIGTERM.
You can disable this by calling
zsys_handler_set (NULL);
Adding the above line in my code disabled the signal handler setup by czmq and now I can use my own signal handler.
Thanks to Pieter Hintjens.
what is the problem ...
From man signal:
The effects of signal() in a multithreaded process are unspecified.
Use sigaction() instead.
I think your problem has nothing to do with CZMQ as such, and is caused by your threading. Specifically, the main thread is catching the signal, and the child thread is not. This is a common trap.
There are several solutions. What I'd perhaps do is sleep/wait in the main thread (you can e.g. use zmq_poll) and then when you get the signal, tell the child threads to end.
Some comments... if you are going to use CZMQ, then why not use its threading facilities, which wrap pthreads in a nicer interface. You have the older zthread class, and the newer zactor class.
I think your main program should be alive. Try this-
int main(int argc, const char *argv[])
{
pthread_t pub_id, sub_id;
signal (SIGINT, sig_int);
pthread_create(&pub_id, NULL, pub_handler, NULL);
pthread_create(&sub_id, NULL, sub_handler, NULL);
pthread_join(pub_id, NULL);
pthread_join(sub_id, NULL);
while(1); // Fix
}
You have changed the signal table using signal function.
signal (SIGINT, sig_int);
So whenever you will give SIGINT signal(ctrl+c), it will call the sig_int function. That is your signal handler. But in that function you are not killing any process.
So whenever you press ctrl + c, your program just call's the sig_int function, That function will print Interrupted for every SIGINT signal.
If you need your program want's to terminate when you press ctrl+c, don't modify the signal table like below.
signal (SIGINT, sig_int);
Instead of that
signal (SIGINT, SIG_DFL);
It will terminate your program, when you press ctrl+c.
Else you can try this also-
void sig_int(int signal){
signal (SIGINT, SIG_DFL); // here i am again changing the signal table to default.
printf (" Interrupted\n");
exit(0);
}
In this case, when you press ctrl+c first time it will call the sig_int function, but when you press second time it will terminate your program. because i have modified the signal table inside your sig_int function.
Related
I'm building a generic program written in C-UNIX (using Linux so I don't care about BSD or WIN functions), that creates two threads to handle the communication with a server.
void init_threads(int socket_desc) {
pthread_t chat_threads[2];
ret = pthread_create(&chat_threads[0], NULL, receiveMessage, (void*)(long)socket_desc);
PTHREAD_ERROR_HELPER(ret, "Errore creazione thread ricezione messaggi");
ret = pthread_create(&chat_threads[1], NULL, sendMessage, (void*)(long)socket_desc);
PTHREAD_ERROR_HELPER(ret, "Errore creazione thread invio messaggi");
}
Since this program will be launched from shell I want to implement the CTRL-C possibility and so did I with this line of code:
signal(SIGINT,kill_handler);
// and its related function
void kill_handler() {
// retrive threads_id
// call pthread_exit on the two threads
printf("Exit from program cause ctrl-c, bye bye\n");
exit(EXIT_SUCCESS);
}
My question is how can I found out the thread ids inside the event handler function and is it correct to call pthread_exit or should I use something else?
Don't call pthread_exit() from a signal handler! It is not required to be async-signal-safe, see signal-safety.
In general, you should do as little as possible in a signal handler. The common idiom is to just set a flag that is periodically checked in your main loop like e.g.
volatile sig_atomic_t exitRequested = 0;
void signal_handler(int signum)
{
exitRequested = 1;
}
int main(void)
{
// init and setup signals
while (!exitRequested)
{
// do work
}
// cleanup
}
Also, use sigaction() for installing signal handlers. See signal() for reasons not to use it.
I have written a code where I have created two child threads from the parent thread.
Then, with receiving a signal from another terminal inside those child threads, I printed the threadID and exited the thread.
I have 2 questions.
I'm receiving the signal from the child thread. Why is it printing the threadID of the parent thread?
After killing the parent thread, how can be the child threads alive??
The Code :
void sig_handler(int signo)
{
if (signo == 1){
printf("%d\n", pthread_self());
pthread_exit(NULL);
}
}
void* doSomeThing(void* arg)
{
printf("In function -> %d\n", pthread_self());
if (signal(1, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGHUP\n");
while(1)
sleep(1);
return NULL;
}
int main(int argc, char *argv[])
{
printf("In function -> %d\n", pthread_self());
char *ch1;
pthread_t tid1, tid2;
ch1 = "random";
int ret1, ret2;
ret1 = pthread_create(&tid1, NULL, &doSomeThing, (void *) ch1 );
ret2 = pthread_create(&tid2, NULL, &doSomeThing, (void *) ch1 );
while(1)
sleep(1);
return 0;
}
Here is the image of the output given in terminal :
The first 3 lines are the 3 threadIDs. 1st one is the Main threadIDs, then the two secondary threads.
Then the threadIDs printed from the following block of code.
if (signo == 1){
printf("%d\n", pthread_self());
pthread_exit(NULL);
}
Why is this happening???
Signals are delivered to the process, not to individual threads. So, you can't have a signal handler just for one thread as you are doing here.
What you can do is block signals you are interested in using pthread_sigmask() and let a dedicated thread handle signals using sigwait(), which is the most common way.
In addition, you can only safely call async-signal-safe functions from within a signal handler. From the Linux signal man page:
Async-signal-safe functions
A signal handler function must be very careful, since processing
elsewhere may be interrupted at some arbitrary point in the execution
of the program. POSIX has the concept of "safe function". If a
signal interrupts the execution of an unsafe function, and handler
either calls an unsafe function or handler terminates via a call to
longjmp() or siglongjmp() and the program subsequently calls an
unsafe function, then the behavior of the program is undefined.
The linked man page has a list of functions that are safe to call from within a signal handler. If the function is not on that list, it is unsafe to call it. No exceptions.
Note that neither printf() nor pthread_exit() are on the list of async-signal-safe functions.
And calling pthread_exit() from within a signal handler creates several other problems:
The thread that exits is generally not under any control. In many cases, the signal can be delivered to any thread.
The exiting thread can leave objects in an unknown state - a mutex can be left locked by a thread that no longer exists, for example.
Any thread cleanup handlers registered with pthread_cleanup_push() will also be called from within a signal handler context.
I was doing a little reading about sigaction() (sources are from my course notes) and I'm not sure I understand this text:
The signal mask is calculated and installed only for the duration of
the signal handler.
By default, the signal “sig” is also blocked when the signal occurs.
Once an action is installed for a specific signal using sigaction,
it remains installed until another action is explicitly requested.
Does this mean that the default signal mask is restored after returning form the signal handler?
Also, do I have to re-install the handler after using it, as if I was using signal()?
Also, there's this piece of code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void termination_handler(int signum) {
exit(7);
}
int main (void) {
struct sigaction new_action,old_action;
new_action.sa_handler = termination_handler;
sigemptyset(&new_action.sa_mask);
sigaddset(&new_action.sa_mask, SIGTERM);
new_action.sa_flags = 0;
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN) {
sigaction(SIGINT,&new_action,NULL);
}
sleep(10);
return 0;
}
So - how exactly will SIGTERM be handled? I can see that the installed handler is termination handler(), but then SIGTERM was added to the signal mask with no use of sigprocmask(). What does this mean? Thanks!
P.s. one last question: why the if statement in main()?
Let's try to understand what's happening with a modified version of your code :
#include <signal.h>
#include <stdio.h>
void termination_handler(int signum)
{
printf("Hello from handler\n");
sleep(1);
}
int main (void)
{
//Structs that will describe the old action and the new action
//associated to the SIGINT signal (Ctrl+c from keyboard).
struct sigaction new_action, old_action;
//Set the handler in the new_action struct
new_action.sa_handler = termination_handler;
//Set to empty the sa_mask. It means that no signal is blocked
// while the handler run.
sigemptyset(&new_action.sa_mask);
//Block the SEGTERM signal.
// It means that while the handler run, the SIGTERM signal is ignored
sigaddset(&new_action.sa_mask, SIGTERM);
//Remove any flag from sa_flag. See documentation for flags allowed
new_action.sa_flags = 0;
//Read the old signal associated to SIGINT (keyboard, see signal(7))
sigaction(SIGINT, NULL, &old_action);
//If the old handler wasn't SIG_IGN (it's a handler that just
// "ignore" the signal)
if (old_action.sa_handler != SIG_IGN)
{
//Replace the signal handler of SIGINT with the one described by new_action
sigaction(SIGINT,&new_action,NULL);
}
while(1)
{
printf("In the loop\n");
sleep(100);
}
return 0;
}
So, if you compile it and launch it, and press Ctrl+C, then you'll have the handler message executed, and then you get back immediately out of the main's sleep. You can do it as many time as you want, and the handler message and the inloop message are still displayed.
So, you give a function, and sigaction does everything needed to hook the signal with your handler.
Now, what about sigterm? If you increase the sleep time in termination_handler, you can type something like "pkill --signal SIGTERM ./a.out" after pressing Ctrl+C. Then, what happens? Nothing! The SIGTERM signal is blocked while termination_handler is running. But once you are back in the main, now the SIGTERM will kill the application.
(Remember, while you are testing this code, you can still kill applications by sending a SIGKILL signal.)
If you want to know more, and have more fun with signals, you have the signal manual and the sigaction manual which tell a lot more. Notice that you also have the detailed description of the sigaction structure.
I have a main application that spawns a seperate thread to process messages off a queue. I have an issue on AIX when I hit CTRL-C as it seems to make some "connection handles" in the thread become invalid. I do have a shutdown hook in the main program catching the SIGINT but on AIX it seems to somehow send a signal to the thread as well...although that is not really possible from what I hear...
Essentially I would like to know if I want the MAIN application to handle ALL signals I am interested in and have the thread/s NEVER handle any signals...is that "good practice"?
If so how can I NOT use "sigwait" in the thread...in fact I do not want any "signal code" in the thread/s...they must simply not receive any signals at all.
I have emptied out all the signals:
sigemptyset(&set);
And have set the SIG_BLOCK
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
So here is a dummy test programe:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void * threadMainLoop(){
//Here I do not want the thread to use "sigwait"....
while(running == TRUE){
//do some thread work and never have any signals come in
}
}
void shutdownHook(int sig){
printf("\nCtrl-C pressed....shutdown hook in main...\n");
}
void signalErrorHandler(int signum){
printf("\nSignal error handler in main...\n");
}
int main(int argc, char *argv[]){
pthread_t thread;
sigset_t set;
int s;
//Catch the following signals in the MAIN thread
(void) signal(SIGINT, shutdownHook);
(void) signal(SIGSEGV, signalErrorHandler);
(void) signal(SIGBUS, signalErrorHandler);
(void) signal(SIGILL, signalErrorHandler);
(void) signal(SIGTERM, signalErrorHandler);
(void) signal(SIGABRT, signalErrorHandler);
sigemptyset(&set); //BLOCK all signals
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
pause();
}
If I just create a thread and have, for example, the SIGINT signal handler in the MAIN thread but do NOT has the SIG_BLOCK set for the thread and the user hits CTRL-C....does the thread get affected at all even though the signal handler in the main thread runs? That seems to be what I am seeing on AIX ;-(
Thanks for the help, much appreciated
Lynton
With s = pthread_sigmask(SIG_BLOCK, &set, NULL); , you're not blocking anything.
Use:
sigfillset(&set);
sets = pthread_sigmask(SIG_SETMASK, &set, NULL);
If you want to block every signal, or explicitly add the signals you want to block to the set if you're using SIG_BLOCK.
After you've created the threads, you need to restore the signal mask, otherwise no threads will catch any signal.
However, looking at your previous question, it might be that the thread catching the signal doesn't handle being interrupted. That is, if you're blocked doing a syscall, and a signal arrives, that syscall gets aborted. Some operating systems defaults to automatically call the system call again, some returns an error and sets errno to EINTR, which the application must handle - and bad things might happen if that's not handled.
Instead, install your signal handlers with sigaction() instead of signal() , and set the SA_RESTART flag, which will cause system calls to automatically restart in case it got aborted by a signal.
Still wrong design.
Do not use CTRL+C to stop an application in a controlled manner.
Use a correctly designed controller app that will be accessible over CORBA, RMI, or some other method to interact with the user and control the background app.
Have fun guys...
I have to code a multithreaded(say 2 threads) program where each of these threads do a different task. Also, these threads must keep running infinitely in the background once started. Here is what I have done. Can somebody please give me some feedback if the method is good and if you see some problems. Also, I would like to know how to shut the threads in a systematic way once I terminate the execution say with Ctrl+C.
The main function creates two threads and let them run infinitely as below.
Here is the skeleton:
void *func1();
void *func2();
int main(int argc, char *argv[])
{
pthread_t th1,th2;
pthread_create(&th1, NULL, func1, NULL);
pthread_create(&th2, NULL, func2, NULL);
fflush (stdout);
for(;;){
}
exit(0); //never reached
}
void *func1()
{
while(1){
//do something
}
}
void *func2()
{
while(1){
//do something
}
}
Thanks.
Edited code using inputs from the answers:
Am I exiting the threads properly?
#include <stdlib.h> /* exit() */
#include <stdio.h> /* standard in and output*/
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <semaphore.h>
sem_t end;
void *func1();
void *func2();
void ThreadTermHandler(int signo){
if (signo == SIGINT) {
printf("Ctrl+C detected !!! \n");
sem_post(&end);
}
}
void *func1()
{
int value;
for(;;){
sem_getvalue(&end, &value);
while(!value){
printf("in thread 1 \n");
}
}
return 0;
}
void *func2()
{
int value;
for(;;){
sem_getvalue(&end, &value);
while(!value){
printf("value = %d\n", value);
}
}
return 0;
}
int main(int argc, char *argv[])
{
sem_init(&end, 0, 0);
pthread_t th1,th2;
int value = -2;
pthread_create(&th1, NULL, func1, NULL);
pthread_create(&th2, NULL, func2, NULL);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = ThreadTermHandler;
// Establish a handler to catch CTRL+c and use it for exiting.
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction for Thread Termination failed");
exit( EXIT_FAILURE );
}
/* Wait for SIGINT. */
while (sem_wait(&end)!=0){}
//{
printf("Terminating Threads.. \n");
sem_post(&end);
sem_getvalue(&end, &value);
/* SIGINT received, cancel threads. */
pthread_cancel(th1);
pthread_cancel(th2);
/* Join threads. */
pthread_join(th1, NULL);
pthread_join(th2, NULL);
//}
exit(0);
}
There are mainly two approaches for thread termination.
Use a cancellation point. The thread will terminate when requested to cancel and it reaches a cancellation point, thus ending execution in a controlled fashion;
Use a signal. Have the threads install a signal handler which provides a mechanism for termination (setting a flag and reacting to EINTR).
Both approaches has caveats. Refer to Kill Thread in Pthread Library for more details.
In your case, it seems a good opportunity to use cancellation points. I will work with a commented example. The error-checking has been omitted for clarity.
#define _POSIX_C_SOURCE 200809L
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void sigint(int signo) {
(void)signo;
}
void *thread(void *argument) {
(void)argument;
for (;;) {
// Do something useful.
printf("Thread %u running.\n", *(unsigned int*)argument);
// sleep() is a cancellation point in this example.
sleep(1);
}
return NULL;
}
int main(void) {
// Block the SIGINT signal. The threads will inherit the signal mask.
// This will avoid them catching SIGINT instead of this thread.
sigset_t sigset, oldset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
// Spawn the two threads.
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread, &(unsigned int){1});
pthread_create(&thread2, NULL, thread, &(unsigned int){2});
// Install the signal handler for SIGINT.
struct sigaction s;
s.sa_handler = sigint;
sigemptyset(&s.sa_mask);
s.sa_flags = 0;
sigaction(SIGINT, &s, NULL);
// Restore the old signal mask only for this thread.
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
// Wait for SIGINT to arrive.
pause();
// Cancel both threads.
pthread_cancel(thread1);
pthread_cancel(thread2);
// Join both threads.
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// Done.
puts("Terminated.");
return EXIT_SUCCESS;
}
The need for blocking/unblocking signals is that if you send SIGINT to the process, any thread may be able to catch it. You do so before spawning the threads to avoid having them doing it by themselves and needing to synchronize with the parent. After the threads are created, you restore the mask and install a handler.
Cancellation points can be tricky if the threads allocates a lot of resources; in that case, you will have to use pthread_cleanup_push() and pthread_cleanup_pop(), which are a mess. But the approach is feasible and rather elegant if used properly.
The answer depends a lot on what you want to do when the user presses CtrlC.
If your worker threads are not modifying data that needs to be saved on exit, you don't need to do anything. The default action of SIGINT is to terminate the process, and that includes all threads that make up the process.
If your threads do need to perform cleanup, however, you've got some work to do. There are two separate issues you need to consider:
How you handle the signal and get the message to threads that they need to terminate.
How your threads receive and handle the request to terminate.
First of all, signal handlers are a pain. Unless you're very careful, you have to assume most library functions are not legal to call from a signal handler. Fortunately, sem_post is specified to be async-signal-safe, and can meet your requirements perfectly:
At the beginning of your program, initialize a semaphore with sem_init(&exit_sem, 0, 0);
Install a signal handler for SIGINT (and any other termination signals you want to handle, like SIGTERM) that performs sem_post(&exit_sem); and returns.
Replace the for(;;); in the main thread with while (sem_wait(&exit_sem)!=0).
After sem_wait succeeds, the main thread should inform all other threads that they should exit, then wait for them all to exit.
The above can also be accomplished without semaphores using signal masks and sigwaitinfo, but I prefer the semaphore approach because it doesn't require you to learn lots of complicated signal semantics.
Now, there are several ways you could handle informing the worker threads that it's time to quit. Some options I see:
Having them check sem_getvalue(&exit_sem) periodically and cleanup and exit if it returns a nonzero value. Note however that this will not work if the thread is blocked indefinitely, for example in a call to read or write.
Use pthread_cancel, and carefully place cancellation handlers (pthread_cleanup_push) all over the place.
Use pthread_cancel, but also use pthread_setcancelstate to disable cancellation during most of your code, and only re-enable it when you're going to perform blocking IO operations. This way you need only put the cleanup handlers just in the places where cancellation is enabled.
Learn advanced signal semantics, and setup an additional signal and interrupting signal handler which you send to all threads via pthread_kill which will cause blocking syscalls to return with an EINTR error. Then your threads can act on this and exit the normal C way via a string of failure returns all the way back up the the start function.
I would not recommend approach 4 for beginners, because it's hard to get right, but for advanced C programmers it may be the best because it allows you to use the existing C idiom of reporting exceptional conditions via return values rather than "exceptions".
Also note that with pthread_cancel, you will need to periodically call pthread_testcancel if you are not calling any other functions which are cancellation points. Otherwise the cancellation request will never be acted upon.
This is a bad idea:
for(;;){
}
because your main thread will execute unnecessary CPU instructions.
If you need to wait in the main thread, use pthread_join as answered in this question: Multiple threads in C program
What you have done works, I see no obvious problems with it (except that you are ignoring the return value of pthread_create). Unfortunately, stopping threads is more involved than you might think. The fact that you want to use signals is another complication. Here's what you could do.
In the "children" threads, use pthread_sigmask to block signals
In the main thread, use sigsuspend to wait for a signal
Once you receive the signal, cancel (pthread_cancel) the children threads
Your main thread could look something like this:
/* Wait for SIGINT. */
sigsuspend(&mask);
/* SIGINT received, cancel threads. */
pthread_cancel(th1);
pthread_cancel(th2);
/* Join threads. */
pthread_join(th1, NULL);
pthread_join(th2, NULL);
Obviously, you should read more about pthread_cancel and cancellation points. You could also install a cleanup handler. And of course, check every return value.
Looked at your updated coded and it still does not look right.
Signal handling must be done in only one thread. Signals targeted for a process (such as SIGINT) get delivered to any thread that does not have that signal blocked. In other words, there is no guarantee that given the three threads you have it is going to be the main thread that receives SIGINT. In multi-threaded programs the best practise is too block all signals before creating any threads, and once all threads have been created unblock the signals in the main thread only (normally it is the main thread that is in the best position to handle signals). See Signal Concepts and Signalling in a Multi-Threaded Process for more.
pthread_cancel is best avoided, there no reason to ever use it. To stop the threads you should somehow communicate to them that they should terminate and wait till they have terminated voluntarily. Normally, the threads will have some sort of event loop, so it should be relatively straightforward to send the other thread an event.
Wouldn't it be much easier to just call pthread_cancel and use pthread_cleanup_push in the thread function to potentially clean up the data that was dynamically allocated by the thread or do any termination tasks that was required before the thread stops.
So the idea would be:
write the code to handle signals
when you do ctrl+c ... the handling function is called
this function cancels the thread
each thread which was created set a thread cleanup function using pthread_cleanup_push
when the tread is cancelled the pthread_cleanup_push's function is called
join all threads before exiting
It seems like a simple and natural solution.
static void cleanup_handler(void *arg)
{
printf("Called clean-up handler\n");
}
static void *threadFunc(void *data)
{
ThreadData *td = (ThreadData*)(data);
pthread_cleanup_push(cleanup_handler, (void*)something);
while (1) {
pthread_testcancel(); /* A cancellation point */
...
}
pthread_cleanup_pop(cleanup_pop_arg);
return NULL;
}
You don't need the foor loop in the main. A th1->join(); th2->join(); will suffice as a wait condition since the threads never end.
To stop the threads you could use a global shared var like bool stop = false;, then when catching the signal (Ctrl+Z is a signal in UNIX), set stop = true aborting the threads, since you are waiting with join() the main program will also exit.
example
void *func1(){
while(!stop){
//do something
}
}