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);
Related
I am using the HTML Server 3 example from boost as my learning tool (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html#boost_asio.examples.http_server_3) for asynchronous message handling.
I have taken the example, and turned it into a library with a server object I can instantiate in my programs. The only thing I have done to the above example is remove the main.cpp and compile it as a library. And it works to the extend that I can instantiate the server object in my code, and pass messages to it from the command line.
Where I am struggling is how to terminate the server gracefully. From the sample code I see this:
server::server(const std::string& address, const std::string& port,
std::size_t thread_pool_size,
Handler &handler)
: thread_pool_size_(thread_pool_size),
signals_(io_service_),
acceptor_(io_service_),
new_connection_(),
request_handler_(handler)
{
// Register to handle the signals that indicate when the server should exit.
// It is safe to register for the same signal multiple times in a program,
// provided all registration for the specified signal is made through Asio.
signals_.add(SIGINT);
signals_.add(SIGTERM);
signals_.async_wait(boost::bind(&server::handle_stop, this));
So an asynchronous thread is set up to listen for signals and respond to them
I have implemented this server object in a thread in my program as follows:
class ServerWorker
{
public:
ServerWorker(std::string theHost, std::string thePort)
{
Host = theHost;
Port = thePort;
}
void Start()
{
try
{
MYRequestHandler handler;
int nCores = boost::thread::hardware_concurrency();
server *mServer = new server(Host, Port, nCores, handler);
svr->run();
}
catch(std::exception &e) { /* do something */ }
}
void Stop()
{
mServer->stop(); // this should raise a signal and send it to the server
// but don't know how to do it
}
private:
std::string Host;
std::string Port;
server *mServer;
};
TEST(BSGT_LBSSERVER_STRESS, BSGT_SINGLETON)
{
// Launch as server on a new thread
ServerWorker sw(BSGT_DEFAULT_IPADDRESS, BSGT_DEFAULT_PORT_STR);
boost::function<void()> th_func = boost::bind(&ServerWorker::Start, &sw);
boost::thread swThread = boost::thread(th_func);
// DO SOMETHING
// How do I signal the server in the swThread to stop?
}
How do I implement the stop() method on the server object to send the signal to itself? I have tried:
1) raise(SIGTERM) - kills the whole program
2) raise(SIGINT) - kills the whole program
raise() is appropriate for having a process signal itself.
void ServerWorker::Stop()
{
std::raise(SIGTERM);
}
Be aware that raise() is asynchronous. It will issue the signal and return immediately. Hence, control may continue before the io_service processes the enqueued SignalHandler.
void run_server()
{
// Launch as server on a new thread
ServerWorker server_worker(...);
boost::thread worker_thread([&server_worker]() { server_worker.Start(); });
...
// Raises SIGTERM. May return before io_service is stopped.
server_worker.Stop();
// Need to synchronize with worker_thread. The `worker_thread` may still be
// in `ServerWorker::Start()` which would go out of scope. Additionally,
// the `worker_thread` is joinable, so its destructor may invoke
// `std::terminate()`.
}
Here is a minimal example demonstrating using Boost.Asio signal handling, raise(), and synchronization:
#include <cassert>
#include <csignal>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
int main()
{
boost::asio::io_service io_service;
// Prevent io_service from running out of work.
boost::asio::io_service::work work(io_service);
// Boost.Asio will register an internal handler for SIGTERM.
boost::asio::signal_set signal_set(io_service, SIGTERM);
signal_set.async_wait(
[&io_service](
const boost::system::error_code& error,
int signal_number)
{
std::cout << "Got signal " << signal_number << "; "
"stopping io_service." << std::endl;
io_service.stop();
});
// Raise SIGTERM.
std::raise(SIGTERM);
// By the time raise() returns, Boost.Asio has handled SIGTERM with its
// own internal handler, queuing it internally. At this point, Boost.Asio
// is ready to dispatch this notification to a user signal handler
// (i.e. those provided to signal_set.async_wait()) within the
// io_service event loop.
std::cout << "io_service stopped? " << io_service.stopped() << std::endl;
assert(false == io_service.stopped());
// Initiate thread that will run the io_service. This will invoke
// the queued handler that is ready for completion.
std::thread work_thread([&io_service]() { io_service.run(); });
// Synchornize on the work_thread. Letting it run to completion.
work_thread.join();
// The io_service has been explicitly stopped in the async_wait
// handler.
std::cout << "io_service stopped? " << io_service.stopped() << std::endl;
assert(true == io_service.stopped());
}
Output:
io_service stopped? 0
Got signal 15; stopping io_service.
io_service stopped? 1
I have a main process and some child process spawn from it. At a point of time i have to give SIGINT signal to all the child process but not to main process. I am unable to store pid's for all child processes. So i used SIG_IGN for ignoring SIGINT in main process and set to default after my action. But it is not working.
Please find my code snippet below:
/* Find group id for process */
nPgid = getpgid(parentPID);
/* Ignore SIGINT signal in parent process */
if (signal(SIGINT, SIG_IGN) == SIG_ERR)
{
cout << "Error in ignoring signal \n");
}
/* Send SIGINT signal to all process in the group */
nReturnValue = kill ( (-1 * nPgid), SIGINT);
if (nReturnValue == RETURN_SUCCESS)
{
cout << "Sent SIGINT signal to all process in group successfully \n";
}
else
{
cout << "Alert!!! Unable to send SIGINT signal to all process in the group \n";
}
/* Set SIGINT signal status to default */
signal (SIGINT, SIG_DFL);
sleep(2);
I am not getting any error. But parent is getting killed. Am i doing anything wrong here?
nPgid = getpgid(parentPID);
What is parentPID? The get the group of the calling process either pass 0 or the result of getpid().
From man getpgid():
getpgid() returns the PGID of the process specified by pid. If pid
is zero, the process ID of the calling process is used. (Retrieving
the PGID of a process other than the caller is rarely necessary, and
the POSIX.1 getpgrp() is preferred for that task.)
From this text above I'd draw the conclusion to do
nPgid = getpgid(o);
#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()
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.
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);