Terminate threads when SIGINT is called - C - c

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.

Related

Why child threads alive after the main threads are killed?

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.

Signal handler getting called in wrong thread

I want to know if its possible to interrupt main thread and ask it to execute some callback. The main thread should continue with what it was doing after completing the callback.
For instance, we have 2 threads t1 and m1 (main thread). t1 will interrupt m1 (main thread) and ask it to call a function with some parameters. The m1 (main thread) will stop doing what it was doing before and will start executing the function. The after finishing the function, it will get back to what it was doing earlier.
I want to replicate what hardware interrupt does. I have one thread that reads data from a file. Then it should ask main thread to call a function. Main thread will be doing something. It should stop doing it and start executing the function. After completing it, main thread should continue with what it was doing
I have written following code using signals
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
static void catch_function(int signo) {
int id = GetCurrentThreadId();
printf("\nThread ID is %d",id);
signal(SIGINT, catch_function);
}
DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
int id = GetCurrentThreadId();
printf("\nChild Thread ID is %d",id);
while(1)
{
Sleep(50);
if (raise(SIGINT) != 0) {
fputs("Error raising the signal.\n", stderr);
return EXIT_FAILURE;
}
}
return 0;
}
int main(void) {
int id = GetCurrentThreadId();
printf("\nMain Thread ID is %d",id);
if (signal(SIGINT, catch_function) == SIG_ERR) {
fputs("An error occurred while setting a signal handler.\n", stderr);
return EXIT_FAILURE;
}
HANDLE thread;
DWORD threadId;
thread = CreateThread(NULL, 0, &MyThreadFunction, NULL, 0, &threadId);
if(!thread)
{
printf("CreateThread() failed");
}
while(1)
{
Sleep(50);
}
return 0;
}
The output of code is
Main Thread ID is 6124
Child Thread ID is 7854
Thread ID is 7854
Thread ID is 7854
So my question is should not the signal handler be called in Main thread? I want main thread to call the handler function not the thread which raise the signal?
please let me know what is the correct way of achieving this.
PS. I have to do it for both windows and linux.
I can only offer advice from a Linux side, but as you said that was of interest too then...
... raise does the following (from the manual page):
The raise() function sends a signal to the calling process or thread.
So in a multi-threaded program it is the thread that calls raise that will get the signal.
On Linux, for threading, you'll probably be using pthreads, in which case you have pthread_kill, this sends a specific signal to a specific thread. You'd need to use pthread_self in the main thread to get the thread id, then pass this to the worker thread. The worker thread can then send signals directly to the main thread.
I suspect you need to find something similar for Windows, but that's not something I know about.
The only one that can interrupt a thread is itself or the Task Scheduler.
If you were to stop someone else you would need direct access to timer hardware.
You can do what Ed Heal said. Use conditional variables and semaphores. My advice is to build up a linked list or even just an array storing what to do and who is the one wich should do it.
See what Windows does to send messages to the program in "event-driven UI".
A MSG struct is given to the application with some integers, like message code, WPARAM and LPARAM.
Define a structure of your own and use it to send messages to each thread (some form of interprocess communication). And, that's important, set a timer to a callback function or keep with your Sleep(50) (or more) to not keep "bothering" your processor for nothing.
Hope this helps and sorry for bad english.

signal handler not working

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.

on_exit and CTRL+C

I've got a small program that opens a file and does some operation on it. I subscribed the file closure to the program termination as follows:
static
void exit_handler (int ev, void *arg)
{
fprintf(stderr, "bye %d\n", WEXITSTATUS(ev));
fclose((FILE *)arg);
}
int main (int argc, char *argv[])
{
FILE *out;
...
out = fopen(argv[1], "wt");
if (out == NULL) {
perror("Opening output file");
exit(EXIT_FAILURE);
}
on_exit(exit_handler, out);
...
}
Trying to execute this I notice that it works properly only if the program terminates normally. In case of CTRL+C (SIGINT) the exit_handler callback is not executed.
Isn't that weird? Should I associate a exit(EXIT_FAILURE) call to the signal handler for SIGTERM? What is the best practice in this case?
on_exit will not be invoked for SIGTERM signals. You need to add a handler for it with signal. For example:
void signalHandler(void)
{
...
}
int main(void)
{
signal(SIGTERM, signalHandler);
}
Also note that SIGKILL can not be caught by design.
First of all, on_exit isn't specified by POSIX (atexit with the same semantics is). Second , the linux manual says:
The on_exit() function registers the given function to be called
at normal process termination, whether via exit(3) or via return from
the program's main().
Getting killed by a signal is not a normal exit for a process so callbacks installed with on_exit and atexit aren't implicitly called.
No, and in fact what you want is impossible. The signal generated by Ctrl+C is asynchronous, meaning it could occur between any two machine instructions in your program depending on when Ctrl+C is hit. As such, unless your program is thoroughly avoiding calling async-signal-unsafe functions anywhere in the main program flow, it's illegal to call async-signal-unsafe functions from the signal handler. exit is async-signal-unsafe, as is most of the default cleanup activity it does (like flushing/closing open files). I would expect the atexit function you want to register (atexit, not on_exit, is the correct name for this function) is also going to want to do async-signal-unsafe things.
If you need to perform cleanup when exiting based on a signal, you need to install a signal handler that does not exit itself, but instead sets a global volatile flag that your main program flow will later inspect (and exit if it's true).
From man page of on_exit,
The on_exit() function registers the given function to be called at
normal process termination, whether via exit(3) or via return from the
program's main().
So you need to explicity hook up a handler for SIGTERM using specific functions from signal.h
Something on the lines of
struct sigaction action;
memset (&action, 0, sizeof(action));
action.sa_handler = sigterm_handler;
if (sigaction(SIGTERM, &action, 0))
{
perror ("sigaction");
return 1;
}
/* SIGTERM handler. */
static void sigterm_handler (int sig)
{
...
}

POSIX pthread programming

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
}
}

Resources