carlosprados11
carlosprados11

Reputation: 53

C++ Continue the execution after signal handler

I am trying to manage a signal in C++ and then continue with the program execution normally. I use signals instead of exceptions because the program blocks itself when a sensor is not connected (I can't change this).

The part of code that raise the signal uses a thread as a timer. Since the threads can't throw exceptions, I have decided to raise a signal (SIGTERM in this case).

The problem starts when I try to continue the program in the same way that with the exceptions but with the signal handler. I make use of the setjmp library to solve the problem:

jmp_buf gBuffer;
void signalHandler(int signal) {
    longjmp(gBuffer, 1);
}

int main() {
    std::signal(SIGTERM, signalHandler);

    if (setjmp(gBuffer) == 0) {
        /* ---------------------
           Part of code that raise the signal
        --------------------- */
    }
}

It works fine, but when the program finishes, a memory error appear:

*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

The backtrace when execute the program in debug mode is:

Thread 2 "EXECUTABLE_FILE" received signal SIGTERM, Terminated.
[Switching to Thread 0x7ffff01f2700 (LWP 31718)]
raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
51  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff78531ab in "THREAD THAT RAISE THE SIGNAL" (futureObj=...)
    at "LINE THAT RAISE THE SIGNAL"
#2  0x00007ffff7856ffd in std::__invoke_impl<void, void (*)(std::future<void>), std::future<void> >
    (__f=<optimized out>) at /usr/include/c++/7/bits/invoke.h:60
#3  std::__invoke<void (*)(std::future<void>), std::future<void> > (__fn=<optimized out>)
    at /usr/include/c++/7/bits/invoke.h:95
#4  std::thread::_Invoker<std::tuple<void (*)(std::future<void>), std::future<void> > >::_M_invoke<0ul, 1ul> (this=<optimized out>) at /usr/include/c++/7/thread:234
#5  std::thread::_Invoker<std::tuple<void (*)(std::future<void>), std::future<void> > >::operator()
    (this=<optimized out>) at /usr/include/c++/7/thread:243
#6  std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(std::future<void>), std::future<void> > > >::_M_run (this=<optimized out>) at /usr/include/c++/7/thread:186
#7  0x00007ffff6e41d80 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x00007ffff714c6db in start_thread (arg=0x7ffff01f2700) at pthread_create.c:463
#9  0x00007ffff688988f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

I really appreciate if someone could help me. I could also change the part of code that raises the signal, throwing an exception, but I don't know how to do that within a thread.

Upvotes: 0

Views: 1718

Answers (1)

darune
darune

Reputation: 10962

You cannot do it the way you envision directly - sorry. Yes, your signal handler gets called, but in generally you cannot (and should not try to) continue execution of the main program from within a signal handler due to the limitations listed of signal handlers (eg. new signals may be blocked from being raised, etc.).

Therefore, your signal handler should set some sort of flag, eg. an atomic bool or condition variable or whatever method you prefer. Then return from the signal handler. Then have a loop near the 'offending code' that can check that and that is then able to return/unwind/terminate the timer.

Upvotes: 1

Related Questions