Signal handling in mutlti-threaded process - c++

I have a basic problem of handling signal in a multi-threaded process.
In my code, I create one sub-thread from the main thread, to listen to a SIGALRM which will be later trigger by main thread (using other function like timer_create gives me the same result, so please don't focus on this).
The problem is, instead of catching the signal, the whole process terminated with a strange "Alarm clock" output on the console.
This is my code:
#include <iostream>
#include <sys/time.h>
#include <unistd.h>
#include <csignal>
using namespace std;
void* run_something(void* args){
//unblock the SIGALRM to be catched
sigset_t sig;
sigemptyset(&sig);
sigaddset(&sig, SIGALRM);
sigprocmask(SIG_UNBLOCK, &sig, NULL); //tried with pthread_sigmask
//wait for SIGALRM
int catchedSig;
sigwait(&sig, &catchedSig);
cout<<"in sub-thread, SIGALRM catched, return"<<endl;
}
int main(int argc, char** argv){
//block SIGALRM in main thread
sigset_t sig;
sigemptyset(&sig);
sigaddset(&sig, SIGALRM);
sigprocmask(SIG_BLOCK, &sig, NULL);
//create new thread
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread, &attr, run_something, NULL);
//trigger SIGARLM after 2s
alarm(2); //tried with timer_create/sigevent
//wait
cout<<"in main thread, waiting for sub-thread to terminate"<<endl;
pthread_join(thread, NULL);
cout<<"in main thread, terminating"<<endl;
return EXIT_SUCCESS;
}
Expected result
in main thread, waiting for sub-thread to terminate
in sub-thread, SIGALRM getting caught, return
in main thread, terminating
Observed result
in main thread, waiting for sub-thread to terminate
Alarm clock
Additional info:
I'm using g++ (Debian 5.4.0-4) 5.4.0 20160609.

Your run_something thread unblocks SIGALRM before calling sigwait for that signal, but this is undefined behavior. sigwait removes a signal from the set of pending (i.e., blocked) signals.
Don't unblock in your thread and you'll see the behavior you expect.

The code shown does not set up any signal handler for SIGARLM.
Therefore on signal reception the OS does as it ought to, namely invoke SIGALRM's default action, that is to terminate the process. Printing "Alarm clock" to the console is part of the default behaviour, BTW.
To fix this set up a signal handler for SIGARLM. This can be done in a portable manner by using sigaction().
Also do not use sigprocmask() in a multi-threaded program, as its behaviour is unspecified. Use pthread_sigmask() instead.
Update:
I missed the code calls sigwait() ... :}
Under this condition fixing this issues does not raise the need to set up a signal handler (which still would solve the issue as well and is valid) but doing as proposed by pilcrow's answer, that is leave the signals blocked prior to calling sigwait()(or sigwaitinfo()).
Additionally make sure to use pthread_sigmask() instead of sigprocmask() for the reason given above.
Unrelated to the question's issue:
I create one sub-thread from the main thread
There is no such concept as "sub"-threads. After having been created all process' threads are "siblings" on the same level. This includes the initial thread started using main(). The "main"-thread is commonly called this way just because of the name of it's thread-function: main

Related

How to run a thread infinitely without blocking main thread in c++?

I am trying to make a native app , and I need a separate thread freezing some values(constant overwriting with delay) in the background and I don't need any return from it to main. So after creating the thread when I detach from it , it does not do the freezing.
pthread_create(&frzTh, NULL, freezingNow, NULL);
pthread_detach(frzTh);
But if I join the thread then it performs freezing but my main thread gets blocked as it waits for the child thread to finish , and since the child runs infinitely , there is no coming out.
pthread_create(&frzTh, NULL, freezingNow, NULL);
pthread_join(frzTh,NULL);
So, I tried using fork() to create a child process instead of thread. Now , I am able to perform all tasks parallel to my main. But , this is causing a lot of memory usage and leads to heating of device.
pid_t pid_c = fork();
if (pid_c == 0 && freeze) {
while (freeze) {
Freeze();
usleep(delay);
}
}
So, what is the best way to do this ?
Best example is game guardian app and it's freezing mechanism.
To do this properly, you need to have a mechanism by which the main thread can cause the child thread to exit (a simple std::atomic<bool> pleaseQuitNow that the child thread tests periodically, and the main thread sets to true before calling pthread_join(), will do fine).
As for why you need to call pthread_join() before exiting, rather than just allowing the main thread to exit while the child thread remains running: there is often run-time-environment code that executes after main() returns that tears down various run-time data structures that are shared by all threads in the process. If any threads are still running while the main-thread is tearing down these data structures, it is possible that the still-running thread(s) will try to access one of these data structures while it is in a destroyed or half-destroyed state, causing an occasional crash-on-exit.
(Of course, if your program never exits at all, or if you don't care about an occasional crash-on-exit, you could skip the orderly shutdown of your child thread, but since it's not difficult to implement, you're better off doing things the right way and avoiding embarrassment later when your app crashes at the end of a demo)
If you wanna do Something as async with Mainthread untill end main ,
I recommand Promise - future in c++
this example :) good luck
#include <future>
#include <iostream>
#include <thread>
void DoWork(promise<int> p)
{
// do something (child thread)
// saved value in p
p.set_value(10);
}
int main(void)
{
promise<int> p;
auto future = p.get_future();
thread worker{ DoWork, std::move(p)};
// do something you want
// return result
int result = future.get();
std::cout<< result <<'\n'; // print 10
}

How to kill/signal other child processes from another child process?

I am having a bit of trouble figuring out exactly how the kill(pid_t pid, int sig) function works when using it in a child process. In my program, I have the parent, and 8 child processes created with fork(). I've been searching and reading online to no avail unfortunately. All of the searched yield results about killing children from the parent process.
I have signal handlers set up in each process, except they are not working correctly.
Basically, I need to signal all of the processes in the process group from the child process "signal_generating_process", but for some reason the signals are not going through correctly.
On the man page, kill(2) says that if I use 0 as the first argument, it will send the signal to all processes in the process group, but its not working correctly for me. I'll include the code for the signal generator as well as one of the signal handlers. Feel free to ask for more information if I haven't included enough. Thank you all very much!
void signal_generating_process(){
signal(SIGINT, end_process_handler);
block_sigusr1();
block_sigusr2();
while(true){
millisleep(randomFloat(.01,.1)); //function I created to sleep for a certain amount of milliseconds
int sig = rand_signal(); //randomly picks between sigusr1 and sigusr2
kill(0, sig);
if(sig == SIGUSR1){ //adds to a counter for sigusr1
pthread_mutex_lock(&shm_ptr->mutex1_sent);
shm_ptr->SIGUSR1_sent++;
pthread_mutex_unlock(&shm_ptr->mutex1_sent);
}
else{ //signal == SIGUSR2 - adds to a counter for sigusr2
pthread_mutex_lock(&shm_ptr->mutex2_sent);
shm_ptr->SIGUSR2_sent++;
pthread_mutex_unlock(&shm_ptr->mutex2_sent);
}
}
}
Process that handles sigusr1 and the signal handler (sigusr2 is the same):
void sigusr1_receiving_process(){
block_sigusr2();
signal(SIGUSR1, sigusr1_handler);
signal(SIGINT, end_process_handler);
while(true){
sleep(1);
}
}
void sigusr1_handler(int signal){
printf("Signal 1 Received\n");
if(signal == SIGUSR1){
pthread_mutex_lock(&shm_ptr->mutex1_received);
shm_ptr->SIGUSR1_received++;
pthread_mutex_lock(&shm_ptr->mutex1_received);
}
}
When these loops go through, "Signal 1 Received" is never printed throughout the course of the entire execution. Is there anything that you can tell is obviously wrong with how I'm handling signals?
Edit: I fixed my problem! Unfortunately, it had nothing to do with what I have above, so I apologize for people who find this question in the future looking for an answer.
Anyway, if you do stumble upon it, maybe it has to do with the way you block signals. I blocked signals incorrectly in the parent process, so they transferred over into the child processes. If you're having this issue, maybe check how you have blocked signals.

C++ & OpenSSL: SIGPIPE when writing in closed pipe

I'm coding a C++ SSL Server for TCP Connections on Linux.
When the program uses SSL_write() to write into a closed pipe, a SIGPIPE-Exception gets thrown which causes the program to shut down. I know that this is normal behaviour. But the program should not always die when the peer not closes the connection correctly.
I have already googled a lot and tried pretty much everything I found, but it seems like nothing is working for me. signal(SIGPIPE,SIG_IGN) does not work - the exception still gets thrown (Same for signal(SIGPIPE, SomeKindOfHandler).
The gdb output:
Program received signal SIGPIPE, Broken pipe.
0x00007ffff6b23ccd in write () from /lib/x86_64-linux-gnu/libpthread.so.0
(gdb) where
#0 0x00007ffff6b23ccd in write () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x00007ffff7883835 in ?? () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
#2 0x00007ffff7881687 in BIO_write () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
#3 0x00007ffff7b9d3e0 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
#4 0x00007ffff7b9db04 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
#5 0x000000000042266a in NetInterface::SendToSubscribers(bool) () at ../Bether/NetInterface.h:181
#6 0x0000000000425834 in main () at ../Bether/main.cpp:111
About the Code:
I'm using a thread which is waiting for new connections and accepting them. The thread then puts the connection information (BIO & SSL) into a static map inside the NetInterface class.
Every 5 seconds NetInterface::sendTOSubscribers() is executed from main(). This function accesses the static map and sends data to every connection in there. This function is also where the SIGPIPE comes from.
I have used signal(SIGPIPE,SIG_IGN) in main() (obviously before the 5-seconds loop) and in NetInterface::SendToSubscribers(), but it is not working anywhere.
Thanks for your help!
You have to call function sigaction to change this behavior either to ignore SIGPIPE or handle it in a specific way with your own signal handler. Please don't use function signal, it's obsolete.
http://man7.org/linux/man-pages/man2/sigaction.2.html
One way to do it (I haven't compiled this code but should be something like this):
void sigpipe_handler(int signal)
{
...
}
int main()
{
struct sigaction sh;
struct sigaction osh;
sh.sa_handler = &sigpipe_handler; //Can set to SIG_IGN
// Restart interrupted system calls
sh.sa_flags = SA_RESTART;
// Block every signal during the handler
sigemptyset(&sh.sa_mask);
if (sigaction(SIGPIPE, &sh, &osh) < 0)
{
return -1;
}
...
}
If the program is multithreaded, it is a little different as you have less control on which thread will receive the signal. That depends on the type of signal. For SIGPIPE, it will be sent to the pthread that generated the signal. Nevertheless, sigaction should work OK.
It is possible to set the mask in the main thread and all subsequently created pthreads will inherit the signal mask. Otherwise, the signal mask can be set in each thread.
sigset_t blockedSignal;
sigemptyset(&blockedSignal);
sigaddset(&blockedSignal, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &blockedSignal, NULL);
However, if you block the signal, it will be pending for the process and as soon as it is possible it will be delivered. For this case, use sigtimedwait at the end of the thread. sigaction set at the main thread or in the thread that generated SIGPIPE should work as well.
I've found the solution, it works with pthread_sigmask.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
return -1;
Thanks to everyone for the help!

Cancelling thread that is stuck on epoll_wait

I'm doing some event handling with C++ and pthreads. I have a main thread that reads from event queue I defined, and a worker thread that fills the event queue. The queue is of course thread safe.
The worker thread have a list of file descriptors and create an epoll system call to get events on those file descriptors. It uses epoll_wait to wait for events on the fd's.
Now the problem. Assuming I want to terminate my application cleanly, how can I cancel the worker thread properly? epoll_wait is not one of the cancellation points of pthread(7) so it cannot react properly on pthread_cancel.
The worker thread main() looks like this
while(m_WorkerRunning) {
epoll_wait(m_EpollDescriptor, events, MAXEVENTS, -1);
//handle events and insert to queue
}
The m_WorkerRunning is set to true when the thread starts and it looks like I can interrupt the thread by settings m_WorkerRunning to false from the main thread. The problem is that epoll_wait theoretically can wait forever.
Other solution I though about is: instead of waiting forever (-1) I can wait for example X time slots, then handle properly no-events case and if m_WorkerRunning == false then exit the loop and terminate the worker thread cleanly. The main thread then sets m_WorkerRunning to false, and sleeps X. However I'm not sure about the performance of such epoll_wait and also not sure what would be the correct X? 500ms? 1s? 10s?
I'd like to hear some experienced advises!
More relevant information: the fd's I'm waiting events on, are devices in /dev/input so technically I'm doing some sort of input subsystem. The targeted OS is Linux (latest kernel) on ARM architecture.
Thanks!
alk's answer above is almost correct. The difference, however, is very dangerous.
If you are going to send a signal in order to wake up epoll_wait, never use epoll_wait. You must use epoll_pwait, or you might run into a race with your epoll never waking up.
Signals arrive asynchronously. If your SIGUSR1 arrives after you've checked your shutdown procedure, but before your loop returns to the epoll_wait, then the signal will not interrupt the wait (as there is none), but neither will the program exit.
This might be very likely or extremely unlikely, depending on how long the loop takes in relation to how much time is spent in the wait, but it is a bug one way or the other.
Another problem with alk's answer is that it does not check why the wait was interrupted. It might be any number of reasons, some unrelated to your exit.
For more information, see the man page for pselect. epoll_pwait works in a similar way.
Also, never send signals to threads using kill. Use pthread_kill instead. kill's behavior when sending signals is, at best, undefined. There is no guarantee that the correct thread will receive it, which might cause an unrelated system call to be interrupted, or nothing at all to happen.
You could send the thread a signal which would interupt the blocking call to epoll_wait(). If doing so modify your code like this:
while(m_WorkerRunning)
{
int result = epoll_wait(m_EpollDescriptor, events, MAXEVENTS, -1);
if (-1 == result)
{
if (EINTR == errno)
{
/* Handle shutdown request here. */
break;
}
else
{
/* Error handling goes here. */
}
}
/* Handle events and insert to queue. */
}
A way to add a signal handler:
#include <signal.h>
/* A generic signal handler doing nothing */
void signal_handler(int sig)
{
sig = sig; /* Cheat compiler to not give a warning about an unused variable. */
}
/* Wrapper to set a signal handler */
int signal_handler_set(int sig, void (*sa_handler)(int))
{
struct sigaction sa = {0};
sa.sa_handler = sa_handler;
return sigaction(sig, &sa, NULL);
}
To set this handler for the signal SIGUSR1 do:
if (-1 == signal_handler_set(SIGUSR1, signal_handler))
{
perror("signal_handler_set() failed");
}
To send a signal SIGUSR1 from another process:
if (-1 == kill(<target process' pid>, SIGUSR1))
{
perror("kill() failed");
}
To have a process send a signal to itself:
if (-1 == raise(SIGUSR1))
{
perror("raise() failed");
}

C++: Thread synchronization scenario on Linux Platform

I am implementing multithreaded C++ program for Linux platform where I need a functionality similar to WaitForMultipleObjects().
While searching for the solution I observed that there are articles that describe how to achieve WaitForMultipleObjects() functionality in Linux with examples but those examples does not satisfy the scenario that I have to support.
The scenario in my case is pretty simple. I have a daemon process in which the main thread exposes a method/callback to the outside world for example to a DLL. The code of the DLL is not under my control. The same main thread creates a new thread "Thread 1". Thread 1 has to execute kind of an infinite loop in which it would wait for a shutdown event (daemon shutdown) OR it would wait on the data available event being signaled through the exposed method/callback mentioned above.
In short the thread would be waiting on shutdown event and data available event where if shutdown event is signaled the wait would satisfy and the loop would be broken or if data available event is signaled then also wait would satisfy and thread would do business processing.
In windows, it seems very straight forward. Below is the MS Windows based pseudo code for my scenario.
//**Main thread**
//Load the DLL
LoadLibrary("some DLL")
//Create a new thread
hThread1 = __beginthreadex(..., &ThreadProc, ...)
//callback in main thread (mentioned in above description) which would be called by the DLL
void Callbackfunc(data)
{
qdata.push(data);
SetEvent(s_hDataAvailableEvent);
}
void OnShutdown()
{
SetEvent(g_hShutdownEvent);
WaitforSingleObject(hThread1,..., INFINITE);
//Cleanup here
}
//**Thread 1**
unsigned int WINAPI ThreadProc(void *pObject)
{
while (true)
{
HANDLE hEvents[2];
hEvents[0] = g_hShutdownEvent;
hEvents[1] = s_hDataAvailableEvent;
//3rd parameter is set to FALSE that means the wait should satisfy if state of any one of the objects is signaled.
dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
switch (dwEvent)
{
case WAIT_OBJECT_0 + 0:
// Shutdown event is set, break the loop
return 0;
case WAIT_OBJECT_0 + 1:
//do business processing here
break;
default:
// error handling
}
}
}
I want to implement the same for Linux. According to my understanding when it would come to Linux, it has totally different mechanism where we need to register for signals. If the termination signal arrives, the process would come to know that it is about to shutdown but before that it is necessary for the process to wait for the running thread to gracefully shutdown.
The correct way to do this in Linux would be using condition variables. While this is not the same as WaitForMultipleObjects in Windows, you will get the same functionality.
Use two bools to determine whether there is data available or a shutdown must occur.
Then have the shutdown function and the data function both set the bools accordingly, and signal the condition variable.
#include <pthread.h>
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t hThread1; // this isn't a good name for it in linux, you'd be
// better with something line "tid1" but for
// comparison's sake, I've kept this
bool shutdown_signalled;
bool data_available;
void OnShutdown()
{
//...shutdown behavior...
pthread_mutex_lock(&mutex);
shutdown_signalled = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cv);
}
void Callbackfunc(...)
{
// ... whatever needs to be done ...
pthread_mutex_lock(&mutex);
data_available = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cv);
}
void *ThreadProc(void *args)
{
while(true){
pthread_mutex_lock(&mutex);
while (!(shutdown_signalled || data_available)){
// wait as long as there is no data available and a shutdown
// has not beeen signalled
pthread_cond_wait(&cv, &mutex);
}
if (data_available){
//process data
data_available = false;
}
if (shutdown_signalled){
//do the shutdown
pthread_mutex_unlock(&mutex);
return NULL;
}
pthread_mutex_unlock(&mutex); //you might be able to put the unlock
// before the ifs, idk the particulars of your code
}
}
int main(void)
{
shutdown_signalled = false;
data_available = false;
pthread_create(&hThread1, &ThreadProc, ...);
pthread_join(hThread1, NULL);
//...
}
I know windows has condition variables as well, so this shouldn't look too alien. I don't know what rules windows has about them, but on a POSIX platform the wait needs to be inside of a while loop because "spurious wakeups" can occur.
If you wish to write unix or linux specific code, you have differenr APIs available:
pthread: provides threads, mutex, condition variables
IPC (inter process comunication) mechanisms : mutex, semaphore, shared memory
signals
For threads, the first library is mandatory (there are lower level syscalls on linux, but it's more tedious). For events, the three may be used.
The system shutdown event generate termination (SIG_TERM) and kill (SIG_KILL) signals broadcasted to all the relevant processes. Hence an individual daemon shutdown can also be initiated this way. The goal of the game is to catch the signals, and initiate process shutdown. The important points are:
the signal mechanism is made in such a way that it is not necessary to wait for them
Simply install a so called handler using sigaction, and the system will do the rest.
the signal is set to the process, and any thread may intercept it (the handler may execute in any context)
You need therefore to install a signal handler (see sigaction(2)), and somehow pass the information to the other threads that the application must terminate.
The most convenient way is probably to have a global mutex protected flag which all your threads will consult regularily. The signal handler will set that flag to indicate shutdown. For the worker thread, it means
telling the remote host that the server is closing down,
close its socket on read
process all the remaining received commands/data and send answers
close the socket
exit
For the main thread, this will mean initiating a join on the worker thread, then exit.
This model should not interfer with the way data is normally processed: a blocking call to select or poll will return the error EINTR if a signal was caught, and for a non blocking call, the thread is regularily checking the flag, so it does work too.