The application I am developing happens to be multi-threaded, and each thread has a critical section code. When user interrupts the application, I need to terminate the threads and save the execution state before terminating the application. To achieve this I coded some checks at random places in the thread function. Below is the minimal code that helps to understand the execution flow.
#include<pthread.h>
#include<signal.h>
#include<stdlib.h>
struct thread_data
{
int quit;
/* other data variables */
};
void* thread_func(void* data)
{
for ( ; ; )
{
/* Non critical section code start */
if (((struct thread_data*) data)->quit) // checks at random places
pthread_exit(NULL);
/* end */
if (((struct thread_data*) data)->quit)
pthread_exit(NULL);
/* Critical section code start */
// Use data{} structure.
/* end */
if (((struct thread_data*) data)->quit)
pthread_exit(NULL);
}
}
int main()
{
sigset_t sigmask;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
pthread_sigmask(SIG_BLOCK, &sigmask, NULL); // SIGINT is blocked by all the threads.
struct thread_data* data = calloc(5, sizeof(struct thread_data));
pthread_t tids[5];
for (int i = 0; i < 5; i++) // initialize the threads.
pthread_create(tids + i, NULL, thread_func, (void*) (data + i));
int signo;
sigwait(&sigmask, &signo); // wait for user interrupt.
for (int i = 0; i < 5; i++) // terminate threads.
{
data[i].quit = 1;
pthread_join(tids[i], NULL);
}
/* Save the execution state */
// Use data{} structure variable
return 0;
}
But this method does not seem to be proficient, When the thread_func scales up, putting these checks at multiple places becomes tiresome. And a point to mention, I cant rely on signal disposition and calling pthread_exit() from signal handler as it is not async-signal-safe function. Is there a better way to achieve this ?