Does the signal() function overwrite other signal calls a process might have set up? I.e. if a SIGINT handler has been setup by a process, and a DLL calls signal(SIGINT,xxx) to handle its own termination code, does the original SIGINT handler get disabled?
The signal() call:
Installs the handler you specify as a new signal handler, and
Tells you what the old handler was.
The new handler will be called instead of the old one. If you want to chain them, you need to do something like:
typedef void (*Handler)(int signum);
static Handler old_int_handler = SIG_IGN;
static void int_handler(int signum) /* New signal handler */
{
/* ...do your signal handling... */
if (old_int_handler != SIG_IGN && old_int_handler != SIG_DFL)
(*old_int_handler)(signum);
}
static void set_int_handler(void) /* Install new handler */
{
Handler old = signal(SIGINT, SIG_IGN);
if (old != SIG_IGN)
{
old_int_handler = old;
signal(SIGINT, int_handler);
}
}
static void rst_int_handler(void) /* Restore original handler */
{
Handler old = signal(SIGINT, SIG_IGN);
if (old == int_handler)
{
signal(SIGINT, old_int_handler);
old_int_handler = SIG_IGN;
}
}
void another_function()
{
/* ... */
set_int_handler();
/* ... */
rst_int_handler();
/* ... */
}
If interrupts were being ignored, this keeps them ignored. If interrupts were being handled by a user-defined interrupt handler, then this calls your signal handling code and the original signal handling code.
Note that the advice from Christian.K about not handling signals in a DLL (shared library) is also relevant and valid. The description above assumes you decide to ignore that advice.
This is not a "literal" answer to your question, but a recommendation: You shouldn't do this in a DLL.
It is unexpected and often annoying for the application that uses the DLL. A DLL should (normally) be "passive" and only provide functions for the application to call.
So rather provide a public function from your DLL that applications are required to call e.g. MyDllCleanup(). Then let the application decide how it calls that function (via a signal handler or other). BTW, the same goes for initialization: rather than relying on DllMain (or _init/_fini with libdl on UNIX) provide explicit functions for applications to call.
Related
I have a process child (created with fork), I want to know in the parent where it dies, and do there something. In the handle function I want to use member-class function, so I have to pass pointer to "this".
I have thought on two way:
Option 1:
use sigaction;
static RpcCmd* rpcCmdPtr = nullptr;// global pointer to save class
in the main:
rpcCmdPtr = this;
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = **sigchldHdl**;
sigaction(SIGCHLD, &act, 0)
/* SIGCHLD handler. */
void **sigchldHdl**(int sig)
{
if(rpcCmdPtr != nullptr)
{
rpcCmdPtr->sigHandler(sig);
}
}
void RpcCmd::sigHandler(int sig)
{ // here are some code...}
Option 2:
use another thread, pass pointer to "this" as argument, and use there signalfd;
static void * sigThread(void * arg)
{
rpcCmd* rpcCmdPtr = static_cast<rpcCmd*>(arg)
sigprocmask(SIG_BLOCK, &mask, NULL)
/* Create a file descriptor from which we will read the signals. */
sfd = signalfd (-1, &mask, 0);
while (1) {
struct signalfd_siginfo si;
res = read (sfd, &si, sizeof(si));
if (si.ssi_signo == SIGCHLD)
// more code ...
}
I want to know WHAT is the best way, and WHY?
Thanks in advance.
Read carefully signal(7) and signal-safety(7) (and remember that most of C++ standard library -including new, containers, etc...- is based upon non async-signal-safe functions like malloc, so you usually cannot call these C++ functions from a signal handler)
You forgot the more portable option 3:
at process initialization, create a pipe(7) (to "self" process)
before entering your event loop install a read handler for that pipe (it would read(2) bytes from it)
install (using sigaction(2)) a signal handler for your signal that simply write(2) one or a few bytes into the pipe. Notice that write is async-signal-safe.
This approach is proposed by Qt, see its Calling Qt Functions From Unix Signal Handlers page.
BTW, many event loop libraries (often above poll(2)...) do handle already SIGCHLD
option 1 is evil.
only async-signal-safe function can be called inside a signal handler. And lots of function can't be called inside a signal handler, eg malloc free and printf
signal handler must be reentrant, your RpcCmd::sigHandler probably is not reentrant
I want to encapsulate the signal handling mechanism into C++ class like WndProc's message dispatching to children's window(s).
class SignalHost : public IRefCount {
private:
SignalHost() { ... (init) ... }
~SignalHost() { ... (restore all signals) ... }
public:
static SignalHost* getSingleton() {
static SignalHost _instance;
return &_instance;
}
public:
bool attach(SignalHandler* handler, int signum) {
... (create a list for signal or push newbie) ...
}
bool detach(SignalHandler* handler, int signum) {
... (remove the handler from list) ...
}
public: /* when the signal occured,
this will invoke all of attached handlers for that signal. */
};
unfortunately, some handler requires special action such as SIG_IGN, SIG_DFL or SIG_ERR. for example, nohup uses SIG_IGN for ignoring SIGHUP.
and many cases can be occurred against the SignalHost.
Signal Handler A executed against SIGSEGV:
this will perform printf("SIGSEGV!\n");only.
Signal Handler B executed against SIGSEGV
this want to bypass the flow into SIG_DFL or handle it like SIG_DFL.
in linux system, the defined signal handlers are just a dummy reference like #define SIG_DFL ((sighandler_t) 0). i already know mechanisms about using directly with SIG_IGN, SIG_DFL or SIG_ERR. but if the signal handlers must be organized within some class and executed as series?
please look at the code below which express my question more detail without OOP concepts.
void my_sigsegv_handler (int signo);
...
struct sigaction sa_sigsegv;
sa_sigsegv.sa_handler = my_sigsegv_handler;
sa_sigsegv.sa_flags = 0;
sigaction(SIGSEGV, &sa_sigsegv, 0);
...
void my_sigsegv_handler (int signo) {
... (handle SIGSEGV as my wish which must be executed) ...
// unfortunately, my code can not handle it correctly...
// so, I want to perform printing errors into stdin without
// returning back into the flow which has caused errors.
exit(-1);
}
Of course, specifying SIG_IGN into SIGSEGV will not be working as my want.
just, this code is an example for explaining i want to do.
Question which i really want to know is, How can I implement the handler which can work like SIG_DFL, SIG_IGN or SIG_ERR after above handler's code??
I am learning ADAPTIVE COMMUNICATION ENVIRONMENT. Here is the tutorial I'm following
http://www.huihoo.org/ace_tao/ACE-5.2+TAO-1.2/ACE_wrappers/docs/tutorials/002/page01.html
I'm getting
error: variable ‘ACE_Sig_Action sa’ has initializer but incomplete type
ACE_Sig_Action sa((ACE_SignalHandler) handler, SIGINT);
error when I'm trying to compile the following code. Any help is appreciated.
// server.cpp,v 1.8 1999/09/22 03:13:30 jcej Exp
/* As before, we need a few ACE objects as well as our Logging_Handler
declaration. */
#include "ace/Acceptor.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/Reactor.h"
#include "handler.h"
/* We'll still use the global reactor pointer. There's a snappy way
around this that shows up in later server tutorials. */
ACE_Reactor *g_reactor;
/* This was hinted at in Tutorial 1. Remember the hand-coded acceptor
that we created there? This template does all of that and more and
better. If you find yourself creating code that doesn't feel like a
part of your application, there's a good chance that ACE has a
template or framework component to do it for you. */
typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor;
/* One of the new things will be a signal handler so that we can exit
the application somewhat cleanly. The 'finished' flag is used
instead of the previous infninite loop and the 'handler' will set
that flag in respose to SIGINT (CTRL-C).
The invocation of ACE_Reactor::notify() will cause the
handle_events() to return so that we can see the new value of 'finished'.
*/
static sig_atomic_t finished = 0;
extern "C" void handler (int)
{
finished = 1;
g_reactor->notify();
}
static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
int
main (int, char **)
{
// Create the reactor we'll register our event handler derivatives with.
ACE_NEW_RETURN (g_reactor,
ACE_Reactor,
1);
// Create the acceptor that will listen for client connetions
Logging_Acceptor peer_acceptor;
/* Notice how similar this is to the open() call in Tutorial 1. I
read ahead when I created that one so that it would come out this
way... */
if (peer_acceptor.open (ACE_INET_Addr (PORT),
g_reactor) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"%p\n",
"open"),
-1);
/* Here's the easiest way to respond to signals in your application.
Simply construct an ACE_Sig_Action object with a "C" function and
the signal you want to capture. As you might expect, there is
also a way to register signal handlers with a reactor but we take
the easy-out here. */
ACE_Sig_Action sa((ACE_SignalHandler) handler, SIGINT);
ACE_DEBUG ((LM_DEBUG,
"(%P|%t) starting up server logging daemon\n"));
// Perform logging service until the signal handler receives SIGINT.
while (!finished)
g_reactor->handle_events ();
// Close the acceptor so that no more clients will be taken in.
peer_acceptor.close();
// Free up the memory allocated for the reactor.
delete g_reactor;
ACE_DEBUG ((LM_DEBUG,
"(%P|%t) shutting down server logging daemon\n"));
return 0;
}
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>;
template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>
#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
You lack the include of ace/Signal.h in your application code.
In C++11, what is the safest (and perferrably most efficient) way to execute unsafe code on a signal being caught, given a type of request-loop (as part of a web request loop)? For example, on catching a SIGUSR1 from a linux command line: kill -30 <process pid>
It is acceptable for the 'unsafe code' to be run on the next request being fired, and no information is lost if the signal is fired multiple times before the unsafe code is run.
For example, my current code is:
static bool globalFlag = false;
void signalHandler(int sig_num, siginfo_t * info, void * context) {
globalFlag = true;
}
void doUnsafeThings() {
// thigns like std::vector push_back, new char[1024], set global vars, etc.
}
void doRegularThings() {
// read filesystem, read global variables, etc.
}
void main(void) {
// set up signal handler (for SIGUSR1) ...
struct sigaction sigact;
sigact.sa_sigaction = onSyncSignal;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGUSR1, &sigact, (struct sigaction *)NULL);
// main loop ...
while(acceptMoreRequests()) { // blocks until new request received
if (globalFlag) {
globalFlag = false;
doUnsafeThings();
}
doRegularThings();
}
}
where I know there could be problems in the main loop testing+setting the globalFlag boolean.
Edit: The if (globalFlag) test will be run in a fairly tight loop, and an 'occasional' false negative is acceptable. However, I suspect there's no optimisation over Basile Starynkevitch's solution anyway?
You should declare your flag
static volatile sig_atomic_t globalFlag = 0;
See e.g. sig_atomic_t, this question and don't forget the volatile qualifier. (It may have been spelled sigatomic_t for C).
On Linux (specifically) you could use signalfd(2) to get a filedescriptor for the signal, and that fd can be poll(2)-ed by your event loop.
Some event loop libraries (libevent, libev ...) know how to handle signals.
And there is also the trick of setting up a pipe (see pipe(2) and pipe(7) for more) at initialization, and just write(2)-ing some byte on it in the signal handler. The event loop would poll and read that pipe. Such a trick is recommended by Qt.
Read also signal(7) and signal-safety(7) (it explains what are the limited set of functions or syscalls usable inside a signal handler)....
BTW, correctness is more important than efficiency. In general, you get few signals (e.g. most programs get a signal once every second at most, not every millisecond).
The code I'm working with has a shared signal handler that switches on the signal number to handle it appropriately.
I'm adding a custom signal. Something like this
static void signal_handler (int s)
{
if ( s == SIGTERM ) clean_up () ;
else if ( s == SIGRTMIN+1 ) ; // do nothing
}
SIGRTMIN and SIGRTMAX are #defines of function calls which initialize static data (in the implementations I've seen on google code search)
Signal handlers are supposed to be non-reentrant. Does the use of static data in the accessor to SIGRTMIN and SIGRTMAX make these macros unsafe to use in a signal handler?
I don't know what implementation you are smoking, but in libc those functions seem to simply return a constant static variable most of the time.
You are right, there is a possible race between the two calls to init(), but that simply just initializes a static int twice to the same constant, hardly a worry.
And, while the static variable is not really that constant, they tell you to only modify said variable at the start of your program(and I think only pthread really modifies it that much).
So no need to worry about these functions(from allocrtsig.c glibc 2.14).
And, if you are really worried, just call SIGRTMIN once before you bind the signal handler. That will get the init() function out of the way.
/* Return number of available real-time signal with highest priority. */
int __libc_current_sigrtmin (void)
{
#ifdef __SIGRTMIN
if (!initialized)
init ();
#endif
return current_rtmin;
}
libc_hidden_def (__libc_current_sigrtmin)
/* Return number of available real-time signal with lowest priority. */
int __libc_current_sigrtmax (void)
{
#ifdef __SIGRTMIN
if (!initialized)
init ();
#endif
return current_rtmax;
}
libc_hidden_def (__libc_current_sigrtmax)