Exiting the p-thread cleanly using sigint as Interrupt - c

i am currently working on raspberry pi and interfacing an ADC with it. The ADC outputs the digital value continuously. The reading of the value and its processing is initiated and executed in a thread, therefore it should run forever. However in order to exit (for some reason) from the thread cleanly, I want to use SIGINT signal handler, which triggers an interrupt and changes the state of volatile variable.
The pseudo-program is as follows:
volatile sig_atomic_t exitThread = 0;
void signalHandler(){
exitThread = 1;
}
void SPI_Port0(){
//initialisation of functions and variables
while(!exitThread){
//do the work
}
if(exitThread){
pthread_exit(NULL);
}
}
void main(){
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = signalHandler;
sigaction(SIGINT, &sa, NULL);
pthread_t SPI0,SPI3;
pthread_create(&SPI0, NULL, SPI_Port0, NULL);
pthread_create(&SPI3, NULL, SPI_Port1, NULL);
pthread_join(SPI0, NULL);
pthread_join(SPI3, NULL);
//printing the results stored in arrays
//the arrays is declared global
}
there are two threads SPI_Port0 and SPI_Port1
doing the same implementation but on two different SPI ports, I want these two threads to exit when the CTRL + C is pressed. The problem i am facing is that, the whole program is exited.
Can someone point me in the right direction. Any help would be appreciated.

Modifications of variable and globals are not shared with child threads because they are other processes.
Fisrt of all you have to catch the signal :
Catch Ctrl-C in C
Then, in the signal interrupt, the child thread must be killed: For pthread, How to kill child thread from the main thread

Related

master error when multiple signal are sent

I got this issue:
I made a program in c, where the main process creates some child process, and these, after a while, are able to send a signal to the main process:
the signal is sent with this code:
kill(getppid(), SIGUSR1);
and the main process, in the while loop is waiting the SIGUSR1 message...
everything is fine, but if I increase the child number and automatically the possibility to have more signals in the same time, the program crash printing the message:
User defined signal 1
the main code is like this:
void signalHandler(int sig, siginfo_t* info, void* vp) {
if (sig == SIGUSR1) {
printf("SIGUSR1 has arrived\n");
} else if (sig == SIGUSR2) {
printf("SIGUSR2 has arrived\n");
}
}
int main(int argc, char const *argv[]) {
struct sigaction action, old_action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_sigaction = signalHandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESTART | SA_NODEFER;
while (1) {
sigaction(SIGUSR1, &action, &old_action);
sigaction(SIGUSR2, &action, &old_action);
}
}
I think the problem is that the signal is sent when the master is still working on the previous signal...but how can I do to fix this thing
thank you very much
It means that the child is sending the signal before the parent process was able to call sigaction() to configure the signal handler. When this happens, the default signal reaction to SIGUSR1 terminates the program:
SIGUSR1 P1990 Term User-defined signal 1
https://man7.org/linux/man-pages/man7/signal.7.html
However, there are many problems with your code. printf() is not safe to be called inside a signal handler (it's AS-Unsafe as defined by POSIX):
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/V2_chap02.html#tag_15_04_03
Also, using SA_NODEFER may create nested signals (another signal handler is called while some signal handler is running) but your program does not protect against a flood. Given enough children this will generate a stack overflow. Finally, the main program keeps running a non-stop infinite loop reconfiguring the signals, while it should have configured them only once outside the loop and blocked inside the loop (for example sigwait() or pselect()):
https://man7.org/linux/man-pages/man2/select.2.html
Finally, if you expect to run a large number of children that might flood the parent with signals, then it would be better to use the real time signal generation function (sigqueue()) rather than kill(). The difference is that with sigqueue(), all signals are queued and SA_NODEFER is not necessary to avoid discarding signals while some other signal handler is running:
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/V2_chap02.html#tag_15_04_02
Final conclusion: the code should be completely rewritten.

to terminate the execution of signal handler in c

i am currently working on project involving the interfacing of an ADC with Ras.-Pi using SPI communication. In the project I am controlling the initialisation of SPI using a timer, which then initiates a signal handler. In the signal handler the SPI transmission takes place and value is being stored in a variable, this variabler i am accesing in a thread and storing the recieved value in an array.
The code runs but the program never comes out of the signal handler. I want the handler to jump to the thread to store the recieved value everytime it processes a value.
Can someone point me to something reliable.
void getSPIvalues(){ // A new Thread which runs parallel and get the values from ADC over SPI
printf("inside thread function\n");
timer_useconds(100, 1);
spiValues[i] = rawData;
printf("from thread, value = %d\n", spiValues[i]);
i++;
}
void signalHandler(int sig){
printf("inside handler function\n");
PWMGenerate(0, 26, 2); //Zyklus = 960 ns, Freuquency = 1,1 MHz, duty clycle= 8 %
char data[2];
bcm2835_spi_transfern(data, sizeof(data));
rawData = (int)(data[0] << 8 | data[1]);
bcm2835_gpio_write(PIN, LOW);
}
//Handler Installation
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = &signalHandler;
sigaction(SIGVTALRM, &sa, NULL);
If I understand correctly, you want a "status update" every x useconds of process execution (rather than of wall clock time, as SIGVTALRM implies ITIMER_VIRTUAL to me).
The safest, simplest way to do this will be to accept a pending signal, instead of delivering that signal to a signal handler.
Before spawning any threads, use pthread_sigmask to SIG_BLOCK at least SIGVTALRM. All new threads will inherit that signal mask. Then, spawn your status thread, detached, which sets an intervalic virtual clock timer and loops, waiting to accept VTALRM:
static void *
my_status_thread(void *ignored) { // spawn me with VTALRM blocked
sigset_t desired; // for me and everyone else!
sigemptyset(&desired);
sigaddset(&desired, SIGVTALRM);
set_itimer_virtual(100, 1); // setitimer()
while (1) {
int s;
(void)sigwait(&desired, &s);
// we got VTALRM, pull the data
PWMGenerate(...);
....
printf("value is %d\n", ...);
}
return NULL; // not reached
}
Aside
It is possible to do this correctly with signal handlers.
It's quite nuanced, and the nuances matter. You should probably be aware that sigaction is preferred over signal and why. That signal disposition (a registered "handler" or "behavior") is a global process attribute, though signal delivery per se and signal masking are per-thread. That sig_atomic_t doesn't necessarily mean volatile, and why you'd care. That very, very few functions can be safely invoked within a signal handler. That sigemptyset(&sa.sa_mask) is, in my opinion, a bit cargo-culty, and you almost certainly want a full mask inside any consequential handlers.
Even then, it's just not worth it. Signal acceptance is a superior idiom to delivery: you react to signals when and where it is safe for you to do so.

Trying to catch SIGINT with sigaction calling handler but still killing process

I'm trying to handle some of the C signals in the program I'm writing to add some safety nets in case of accidental closure etc. I've been trying to set up a signal handler for SIGINT using sigaction, and I can see the handler is being called, but it's not stopping the program from being killed anyway.
Trying to use signal with SIG_IGN works fine, however stops me being able to use custom handling. I've tried using signal(...) with my handler, and sigaction(...), and neither are actually working.
void handler(int SIG) {
//I know this is unsafe just for testing.
printf("Handled signal %d!\n", SIG);
//No actual logic for now.
}
void initializer() {
//...
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
//This doesn't work.
sigaction(SIGINT, &sa, NULL);
//This also didn't work.
// signal(SIGINT, handler);
//...
}
I believed that handling the signal would stop it by default, and everything I've seen online has indicated this should be enough, but I still receive:
^CHandled signal 2!
And then the process is killed...

Will this code block all signals to spawned thread but still catch some in MAIN()?

I wrote a similar question at How to block all SIGNALS in thread WITHOUT using SIGWAIT? but must admit I still need 100% clarity on the topic...C is not my day job ;-) Sorry for the similar question....
All i need 100% clarification on is:
I want to block all signals from going to the thread I create, but I want to catch the signals mentioned below in the MAIN thread, hence the SIG_UNBLOCK after the thread creation.
Also very important is to prevent any interruptions to libraries I have no control over from being "disturbed" during i.e. a SIGINT. I have a situation where a WAIT step is happening in a thread on a "message GET from a queue". That wait step seems to reject SIGINT even though the signal handler is defined in main, hence the SA_RESTART below.
Could you please let me know if the code below will accomplish this? I am pretty sure it is ok.
Thanks for the help, much appreciated
Lynton
The following is a snippet of the MAIN program:
int main(int argc, char * argv[]){
sigset_t set;
struct sigaction sa_shutdown;
struct sigaction sa_error;
//Shutdown hook for CTRL-C
sa_shutdown.sa_handler = shutdownHook;
sigemptyset(&sa_shutdown.sa_mask);
sa_shutdown.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa_shutdown, NULL);
//Error handlers for erroneous signals
sa_error.sa_handler = signalErrorHandler;
sigemptyset(&sa_error.sa_mask);
sa_error.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa_error, NULL);
sigaction(SIGBUS, &sa_error, NULL);
sigaction(SIGILL, &sa_error, NULL);
sigaction(SIGTERM, &sa_error, NULL);
sigaction(SIGABRT, &sa_error, NULL);
//BLOCK all SIGNALS in threads
sigfillset(&set);
rc = pthread_sigmask(SIG_BLOCK, &set, NULL);
if(rc != 0){
printf("Thread sigmask failed\n");
exit(1);
}
rc = pthread_create(&outboundThread, NULL, outboundThreadMainLoop, (void *)argv);
if(rc != 0){
printf("Thread creation failed\n");
exit(1);
}
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
pthread_join(outboundThread, NULL);
return 0;
}
Regarding to block all signals, your code looks OK to me.
Anyway I'd say you should not block SIGFPE, SIGILL, SIGSEGV, or SIGBUS.
pthread_sigmask()'s man page says: "If any of the SIGFPE, SIGILL, SIGSEGV, or SIGBUS signals are generated while they are blocked, the result is undefined, unless the signal was generated by the kill() function, the sigqueue() function, or the raise() function."
Regarding "... interruptions to libraries ...": If your are referring to any call into libraries from a thread created the way you did in your example you, I'd also say that's OK, they won't be interrupted.

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