POSIX Threads behaviour different between HP-UX and Solaris 10 - c++

I'm migrating a multi threaded application from HP-UX to Solaris and so far, everything is OK except for one thing! The application has a thread that is handling the signals and, when some of them are received, it runs some cleaning (logging, kill child processes and so on).
I've reduced the code as much as it was possible to make a somehow simple example showing the problem:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <synch.h>
#include <iostream>
#include <unistd.h>
using namespace std;
pthread_t m_signalHandlerThread;
sigset_t m_signalSet;
void signalHandler()
{
while ( true )
{
cout << "SigWait..." << endl;
sigwait( &m_signalSet, &sig );
cout << "Signal!! : " << sig << endl;
break;
}
cout << "OUT" << endl;
}
void* signalHandlerThreadFunction( void* arg )
{
signalHandler();
return (void*)0;
}
int main()
{
sigemptyset( &m_signalSet );
sigaddset( &m_signalSet, SIGQUIT ); //kill -QUIT
sigaddset( &m_signalSet, SIGTERM ); //kill
sigaddset( &m_signalSet, SIGINT ); //ctrl-C
sigaddset( &m_signalSet, SIGHUP ); //reload config
if ( pthread_create( &m_signalHandlerThread, NULL, signalHandlerThreadFunction, NULL ) )
{
cout << "cannot create signal handler thread, system shut down.\n" << endl;
}
int iTimeout = 0;
while (1)
{
if (iTimeout >= 10)
break;
sleep(1);
iTimeout++;
cout << "Waiting... " << iTimeout << endl;
}
cout << "END" << endl;
exit (0);
}
Using compile command lines:
Solaris:
CC -m64 -g temp.cpp -D_POSIX_PTHREAD_SEMANTICS -lpthread
HP-UX:
/opt/aCC/bin/aCC +p +DA2.0W -AA -g -z -lpthread -mt -I/usr/include temp.cpp
Running both applications, the behaviour (pressing CTRL+C while in the 10 seconds loop):
HP-UX:
./a.out
SigWait...
Waiting... 1
Waiting... 2
Signal!! : 2 <---- CTRL + C
OUT
Waiting... 3
Waiting... 4 <---- CTRL + C again to terminate
Solaris:
./a.out
SigWait...
Waiting... 1
Waiting... 2 <---- CTRL + C
^C
Any help will be more then welcome since I'm already tearing my hair (not much left) :)!
Thanks!

It's unspecified which of your 2 threads will handle SIGINT. If you need only one of your threads to handle the signal, you need to block that signal in all the other threads you have.

You should block signals to other threads by using pthread_sigmask. that page also contains an example for a program with a signal handling thread.

About the only way how to handle signals well in multithreaded application is to do the following:
Block all signals in main() early, before any other threads are spawned, using pthread_sigmask().
Spawn a signals handling thread. Use sigwait() or sigwaitinfo() to handle the signals in a simple loop.
This way no threads except the one dedicated for signal handling will get the signals. Also, since the signal delivery is synchronous this way, you can use any inter-thread communication facilities you have, unlike inside classic signal handlers.

This is rather unorthodox way to handle signals. If you want to marry the signals and threads, better choice would be to have the usual signal handlers from where the signal is serialized internally to another thread which is responsible for the actual handling of the event.
That is also a better option, as it is undefined which thread in an MT application receives the signal. Any threads which doesn't have the signal blocked might receive it. If you have 2 threads (and you have two threads in the example) then any of the threads might get the SIGINT.
You might want to check sigprocmask() as a way to tell OS that SIGINT should be blocked in a thread. That should be done for every thread, IIRC even the one calling sigwait().
Edit1. Actually I'm wrong about the "should be done for every thread" bit above. A new thread inherits its signal mask from the current thread. I have realized that that can't be true because that would have introduced the race condition: signal arrives at the time when new thread created but hasn't yet set its signal mask. In other words, it is sufficient to set the signal mask in the main thread.

Related

Toggling logging functionality using signals on a multithreaded program

I am looking to put in some code (temporary at the moment, but as a thought experiment, I am considering working it in long term), that would accomplish two things.
Allow toggling of logs via signals.
Trap all catchable signals and output pid/thread/signal info to the logs, followed by returning to default behavior.
here is some compiling pseudo-code which shows what I would like to achieve.
#include <iostream>
#include <csignal>
#include <thread> // for this_thread
#include <unistd.h> // For gitpid() and fork()
#include <cstdlib>
// What is a save way of determining the number of
// available signals
// ** Externally defined values
const int verbose_debug_signal = 30;
const int trace_logging_enabled_default = 0;
// ** Component Control Class Definition Start
volatile sig_atomic_t trace_logging_enabled
= trace_logging_enabled_default;
void handle_signal(int sig)
{
std::cout << "Process PID: " << std::dec << getpid()
<< " Caught signal " << std::dec
<< sig << " on thread 0x" << std::hex
<< std::this_thread::get_id() << "\n";
if(sig == verbose_debug_signal)
{
trace_logging_enabled = ~trace_logging_enabled;
std::cout << "Trace Logging "
<< (!!trace_logging_enabled ? "enabled\n" : "disabled\n");
}
else
{
signal(sig, SIG_DFL);
raise(sig);
}
}
class ComponentControlClass
{
public:
ComponentControlClass()
: trace_logging_enabled_ptr(&trace_logging_enabled)
{}
~ComponentControlClass(){}
private:
volatile sig_atomic_t *trace_logging_enabled_ptr;
};
int main()
{
for(int i = 1; i < NSIG; ++i)
{
signal(i, handle_signal);
}
// BAH! stupid SIP strikes again. I think I would
// have to sign this to make it work.
// pid_t children[3];
// for(auto child : children)
// children[child] = fork();
while(1);
return 0;
}
Compiled with the -O3 flag to make sure Volatile fields don't get clobbered. The result of running the code in window 1 and sending a "kill -30 " in window 2, exactly 4 times:
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging enabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging disabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging enabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging disabled
This is exactly what I hoped would happen. In this example this class would represent a component control class which is the entry point for our shared objects using a homegrown framework. In other words, this is where I would need to pass external elements to the schema, like a pointer to volatile memory indicating the log state?
My question(s)
I've never seen anyone do anything like this so I am certain there is a good reason. I am trying to understand the implications.
I found a few articles on complex signal handling, and I was having trouble determining what applied. For all other signals aside from the one I am using to toggle I am trapping and re-enabling, so I wouldn't think this would be an issue. Is it?
When the toggling signal is sent I would want to propagate the logging state to
child processes. I haven't been able to simulate this easily on my Mac because of
SIP, but I haven't quite figured out how I would do this. Only confirmation that it won't happen by itself, because signals work on a per-thread basis.
Now that I'm bouncing between linux and Mac, I am seeing that signal.h is pretty different. My main concern is that different macros are used for the max interrupt and apple seems to only have 32 interrupts where linux uses 64. Is there a boilerplate way of approaching the signals (specifically the max/min values) which is more portable? Something like this but hopefully more robust:
int sigma = 0;
#ifdef LINUX
sigmax = _NSIG;
#elif APPLE
sigmax = NSIG;
#endif

Understanding how multithreading works with Boost io_service

I'm learning multithreading and Boost libraries (Asio in particular) and I'm having a hard time understanding how the following code works (slightly modified from Boost.org tutorials)
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
class printer
{
public:
printer(boost::asio::io_service& io)
: timer1_(io, boost::posix_time::seconds(1)),
timer2_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer1_.async_wait(boost::bind(&printer::print1, this));
timer2_.async_wait(boost::bind(&printer::print2, this));
}
~printer()
{
std::cout << "Final count is " << count_ << std::endl;
}
void print1()
{
if (count_ < 10)
{
std::cout << "Timer 1: " << count_ << std::endl;
++count_;
timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(2));
timer1_.async_wait(boost::bind(&printer::print1, this));
}
}
void print2()
{
if (count_ < 10)
{
std::cout << "Timer 2: " << count_ << std::endl;
++count_;
timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(2));
timer2_.async_wait(boost::bind(&printer::print2, this));
}
}
private:
boost::asio::deadline_timer timer1_;
boost::asio::deadline_timer timer2_;
int count_;
};
void saysomething()
{
std::string whatyasay;
std::cin >> whatyasay;
std::cout << "You said " << whatyasay << std::endl;
}
int main()
{
boost::asio::io_service io;
printer p(io);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
io.run();
std::cout << "Hey there\n";
t.join();
return 0;
}
Which results in the following output
Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10
What I would've expected from this code was that thread t would be in charge of running the io_service, meaning that other operations could take place in the meantime.
Instead, the code behaves as usual, aka, io.run "blocks" the code flow until the timers inside the printer object stop launching async_waits, so "hey there" is only printed after the timers are not working anymore.
But that's not all: from my understanding, io_services don't stop running after the run() method is called as long as there's work associated to them (be it a work object or, in this case, timers). With that said, since the thread is associated to the io_service, I wonder why the io_service would stop running in the first place: after all, the thread is "linked" to the io_service and keeps on running on its own; this is obviously linked to the fact that I clearly didn't understand what this thread is doing in the first place.
Things got even more complicated when I added the "saysomething" method into the pot: I wanted to be able to write something and having that string printed WHILE the 2 timers kept working. The code I used was the following:
int main()
{
boost::asio::io_service io;
printer p(io);
boost::thread t(&saysomething);
io.run();
std::cout << "Hey there\n";
t.join();
return 0;
}
With the following result:
Timer 1: 0
Timer 2: 1
Timer 1: 2
Timer 2: 3
Timer 1: 4
Timer 2: 5
Timer 1: 6
Timer 2: 7
ghg //<--- my input
You said ghg
Timer 1: 8
Timer 2: 9
Hey there
Final count is 10
It works fine, but now that there is no thread associated to the io_service, what was its purpose in the first place?
To sum up my 3 questions are:
Why isn't the "Hey there" string immediately printed rather than waiting for the io_service to stop running?
How exactly does the io_service stop running if a thread is linked to it, which should be equivalent to the io_service having work to do?
Since the thread wasn't allowing the "code flow" to move forward, and linking said thread to my method instead of the io_service didn't cause any error, what was the purpose of that thread in the first place?
Why isn't the "Hey there" string immediately printed rather than waiting for the io_service to stop running?
main's thread also blocks on the io_service before printing, so "Hey there" doesn't print until the service stops.
How exactly does the io_service stop running if a thread is linked to it, which should be equivalent to the io_service having work to do?
The thread is not what's keeping the io_service alive, the timer tasks are. The io_service is actually the one keeping the thread alive here. The work the service has is waiting on the timers, so until the timers expire, the service has work to do.
Since the thread wasn't allowing the "code flow" to move forward, and linking said thread to my method instead of the io_service didn't cause any error, what was the purpose of that thread in the first place?
The purpose of calling run from a thread is to donate that calling thread to the io_service. Until run exits, the service owns that thread, and that thread is part of the service's thread pool. Any task you post to the service may be handed to that thread while it is in the service's pool. When you added the second thread, that second thread wasn't interacting with the service at all because it didn't call run. Thus, it's not part of the service's thread pool.

Handling signals from child process in Bash Scripts

I am trying to trap a signal raised by a child process. However, my trap callback function is never called. I have the following test code
#include <csignal>
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
std::this_thread::sleep_for (std::chrono::seconds(5));
std::cout << ">>> Signal Sent!" << std::endl;
raise(SIGUSR1);
return 0;
}
And this bash script
set -bm
set -e
KEEP_GOING=true
sigusr1()
{
echo "SIGUSR1 Recieved"
KEEP_GOING=false
}
trap sigusr1 SIGUSR1
./signalTest &
while $KEEP_GOING ; do
sleep 1s
echo "Waiting for signal"
done
When I run it I get the following
Waiting for signal
Waiting for signal
Waiting for signal
Waiting for signal
>>> Signal Sent!
[1]+ User defined signal 1 ./signalTest
Waiting for signal
Waiting for signal
Waiting for signal
Waiting for signal
Waiting for signal
^C
From the output I see that the signal is in fact sent, and in some capacity received. However the callback function in my trap is not executed.
Any thoughts?
raise sends the signal to the calling thread.
kill sends a signal to the specified process or thread.
To send the signal to the parent process, instead of
raise(SIGUSR1);
do
#include <unistd.h>
// ...
kill(getppid(), SIGUSR1);

Why is signalhandler not outputting anything?

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;
void sighandler(int sig) {
cout << "signal received" << endl;
}
int main() {
int pid= getpid();
cout << pid << endl;
signal( SIGUSR1, sighandler );
sigset_t accept;
sigaddset( &accept, SIGUSR1 );
int s;
sigwait(&accept, &s);
cout << s << endl;
return 0;
}
When I run this program and send a SIGUSR1 signal to it via "kill -s SIGUSR1 $pid" it just outputs the number of the signal (10) but not the text in sighandler. I don't understand why. This is on a Linux System.
From sigwait - wait for queued signals
DESCRIPTION
The sigwait() function selects a pending signal from set, atomically clears it from the system's set of pending signals, and returns that signal number in the location referenced by sig.
So, by using sigwait(), the signal is already delivered and dealt with by your program.
When you remove the sigwait call and do a sleep or busy waiting, the SIGUSR1 signal will be delivered to your signal handler and the message "signal received" will be printed.
You're getting this behavior because when you call sigwait() your thread gets put to sleep and control gets passed to the OS. When you send the SIGUSR1 signal, it is getting handled by the OS, and then the OS wakes up your thread and passes control back. Even though you've registered a signal handler, your handler is not getting called because the signal has been handled by the time your thread is re-awakened.
I am trying to find a definitive reference, but it appears that the signal handler and sigwait are mutually exclusive. If you handle the signal synchronously, using sigwait, the handler is never invoked.
For a discussion, see About the ambiguous description of sigwait()

How to handle a ctrl-break signal in a command line interface

Before I begin, I want to clarify that this is not a command-line tool, but an application that accepts commands through it's own command-line interface.
Edit: I must apologize about my explanation from before, apparently I didn't do a very good job at explaining it. One more time...
I am building a command-line interface application that accepts commands from a user. I have a signal handler setup to catch the signals, which then sets a flag that I need to terminate the application. The problem I'm having is all of the console functions I can find are blocking, which means that I can't detect that I need to exit from my console processing loop until the user presses a key (or enter, depending on the function).
Is there some standard way I can do either non-block console interaction, or is there an elegant way to structure the program so that if I just terminate from the signal thread, that everything will be handled and released properly (please don't mis-understand this, I know how this could be done using locking and releasing the resources from the signaling thread, but this could get messy, so I'd rather avoid it)
Hopefully that explanation makes more sense...
OK - this is working for me on Windows & is portable - notice the #ifdef SIGBREAK - this isn't a standard signal.
#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
namespace
{
volatile sig_atomic_t quit;
void signal_handler(int sig)
{
signal(sig, signal_handler);
quit = 1;
}
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
signal(SIGBREAK, signal_handler);
#endif
/* etc */
while (!quit)
{
string s;
cin >> s;
cout << s << endl;
}
cout << "quit = " << quit << endl;
}
On *nix, you can use the signal function to register a signal handler:
#include <signal.h>
void signal_handler(int sig)
{
// Handle the signal
}
int main(void)
{
// Register the signal handler for the SIGINT signal (Ctrl+C)
signal(SIGINT, signal_handler);
...
}
Now, whenever someone hits Ctrl+C, your signal handler will be called.
In Windows: SetConsoleCtrlHandler
On a *nix based system you might not really need a signal handler for this to work. You could specify that you want to ignore the SIGINT call
int main(void)
{
// Register to ignore the SIGINT signal (Ctrl+C)
signal(SIGINT, SIG_IGN);
while(1)
{
retval = my_blocking_io_func();
if(retval == -1 && errno == EINTR)
{
// do whatever you want to do in case of interrupt
}
}
}
The important way that this works is to recognize that non-blocking functions do get interrupted. Normally, you would realize that the blocking function failed (e.g. read()) and reattempt the function. If it was some other value you would take the appropriate error related action.
A better *nix solution that is thread safe is to use pthread_sigmask() instead of signal().
For example, this is how you signore SIGINT, SIGTERM, and SIGPIPE in the current thread and future spawned threads:
sigset_t waitset;
sigemptyset(&waitset);
sigaddset(&waitset, SIGINT);
sigaddset(&waitset, SIGTERM);
sigaddset(&waitset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &waitset, NULL);