Can anyone give me the steps or even the code for the following situation:
A process which contains multiple thread, and of these threads is responsible of catching a user defined signal SIGUSR1. Only this thread should be capable of receiving this signal, and upon the reception of this signal I do some stuff.
In my situation the signal is being sent by a Kernel Module to my Process ID. Then it is the responsibility of my process to deliver it to the correct listening thread, which has also established the Signal Handler i.e. the signal handler is not in the main thread.
I already did some code which runs for a single-thread process, but I have a problem in running it in multiple thread environment.
I am running my code on Linux Ubuntu 12.04.3 with Kernel Version 3.8.0-29. And for the creation of the process I am mixing between Boost Threads and POSIX threads API.
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <string.h>
/* Value of the last signal caught */
volatile sig_atomic_t sig_value;
static void sig_handler(const int sig_number, siginfo_t *sig_info, void *context)
{
if (sig_number == SIGSEGV)
{
error_sys("Error at address 0x%lx", (long)sig_info->si_addr);
exit(-1);
}
sig_value = sig_number;
}
int init_signal_catcher()
{
struct sigaction sig_action; /* Structure describing the action to be taken when asignal arrives. */
sigset_t oldmask; /* Signal mask before signal disposition change. */
sigset_t newmask; /* Signal mask after signal disposition change. */
sigset_t zeromask; /* Signal mask to unblock all signal while suspended. */
/* Define signal mask and install signal handlers */
memset(&sig_action, 0, sizeof(struct sigaction));
sig_action.sa_flags = SA_SIGINFO;
sig_action.sa_sigaction = sig_handler;
/* Examine and change a signal action. */
sigaction(SIGHUP, &sig_action, NULL);
sigaction(SIGINT, &sig_action, NULL);
sigaction(SIGTERM, &sig_action, NULL);
sigaction(SIGSEGV, &sig_action, NULL);
sigaction(SIGUSR1, &sig_action, NULL);
/* Block SIGHUP, SIGINT, SIGTERM, SIGSEGV and SIGUSR1 signals. */
sigemptyset(&newmask);
sigaddset(&newmask, SIGHUP);
sigaddset(&newmask, SIGINT);
sigaddset(&newmask, SIGTERM);
sigaddset(&newmask, SIGSEGV);
sigaddset(&newmask, SIGUSR1);
/* Examine and change blocked signals. */
pthread_sigmask(SIG_BLOCK, &newmask, &oldmask);
/* Initialize the empty signal set. */
sigemptyset(&zeromask);
sig_value = 0;
while ((sig_value != SIGINT) && (sig_value != SIGTERM))
{
sig_value = 0;
/*
* Go to sleep (unblocking all signals) until a signal is catched.
* On return from sleep, the signals SIGHUP, SIGINT, SIGTERM and
* SIGUSR1 are again blocked.
*/
printf("Suspending on %lu mask.", zeromask);
// Wait for a signal.
sigsuspend(&zeromask);
switch(sig_value)
{
printf("Caught Signal %d", sig_value);
case SIGUSR1:
printf("Caught SIGUSR1");
break;
}
}
return 0;
}
The signals need to be blocked in every thread. The safest way to do this is to block them in the first thread before any others are created. Then a single, specially chosen thread can call sigsuspend() and only that thread will execute the signal handlers.
void *signal_handling_thread(void *whatever) {
sig_value := 0
while (sig_value not in (SIGTERM, SIGINT)) {
sigsuspend(empty_mask)
...
}
...
}
int main(int argc, char **argv) {
block_relevant_signals(); // SIG_BLOCK HUP, TERM, USR1, etc.
catch_relevant_signals(); // SA_SIGINFO ...
spawn_signal_handling_thread(); // spawned with relevant signals blocked
for (int i = 0; i < NUM_WORKERS; i++) {
spawn_worker_thread(); // spawned with relevant signals blocked
}
...
}
It's time to refactor your code to break apart concerns — do global process attribute manipulation in one place, signal-specific reaction in another, etc.
In your signal handler, you are calling exit(-1). exit(-1) is not asynchronous signal-handler safe. Use _exit(-1) instead.
The difference between the two functions is that exit() calls all of the registered atexit() routines (including C++ static destructors). Before exit() does that shutdown step, it uses pthread_mutex_lock() to ensure a thread-safe shutdown. If the lock happens to be held by another thread, your program will deadlock.
_exit() skips those atexit routines and terminates the process.
I'm not familiar with error_sys(), but it looks like it ends up using printf()/fprintf(). Those routines also tend to be protected by mutexes.
Here is an example to organize which thread gets which signal using pthread_sigmask: http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html
Related
I'm trying to write a multithreaded program which one thread (variable thread in below) is responsible to any asynchronous signals that might be set to this process.
I am facing thread that uses sigwait() but does not react to any signals have been sent to process. (like SIGUSR1 in below).
static void * signal_thread(void *arg = nullptr)
{
int sig = -1;
sigset_t sigset;
sigfillset(&sigset);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
while(1)
{
int s = sigwait(&sigset, &sig);
if(s == 0)
printf("SIG %d recieved!...\n", sig);
usleep(20);
}
}
int main()
{
sigset_t signalset;
pthread_t thread;
pthread_create(&thread, NULL, &signal_thread, nullptr);
sigfillset(&signalset);
pthread_sigmask(SIG_BLOCK, &signalset, NULL);
while(1)
{
raise(SIGUSR1);
usleep(20);
}
}
The problem is concerned to two issues:
First, call of raise in main sent signal only to main thread not whole process.
Secondly, std::cout should be used instead of printf in signal_thread.
raise(sig) is the equivalent of calling pthread_kill(pthread_self(), sig).
Since the main thread raise()s the signal, the SIGUSR1 will be generated for that thread and not for any other. Thus, your signal_thread will be unable to sigwait() for the USR1, which will be held pending for the thread that generated it.
I test that on Linux and it seems that when the tracee is in a signal handler, the tracer can use ptrace() to attach to it, as usual. But since tracee is in a signal handler, some functions might not be OK to invoke because of the asyn-signal-safe problem. So, is there any methods to detect that situation after calling ptrace()?
This recent discussion may interest you.
The short answer is that you can tell whether inferior (tracee) is in a signal handler by unwinding its stack, and looking for rt_sigreturn entry.
That is the entry that GDB prints as <signal handler called>.
However, the question is: why do you care?
Presumably it is to prevent your debugger from calling into the tracee when your end user asks you to perform equivalent of (gdb) call malloc(10).
Note that:
GDB does not prevent end-user from doing so. If the process corrupts its heap or deadlocks as the result, it's the end user's problem, not GDB's.
It is impossible for the debugger to know what functions should be allowed or disallowed, and this determination depends on whether the signal is synchronous and where it originates. For example:
void handler(int signo)
{
while (1)
{
char *p = malloc(20); // perfectly safe (but only in this program)
free(p);
}
}
int main()
{
signal(SIGINT, handler);
kill(getpid(), SIGINT);
return 0; // control never reaches here
}
It turns out that determining whether or not you are currently in a signal handler is trivial with libunwind:
Assume that you have build libunwind properly:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* assume that you have build libunwind properly */
#include "./libunwindout/include/libunwind.h"
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
void show_backtrace(void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while(unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
/* Upon unwinding to a signal handler, you get a "1" */
printf("Is in a signal handler [%d]\n",
unw_is_signal_frame(&cursor));
printf("ip = %lx, sp = %lx \n", (long)ip, (long)sp);
}
}
struct sigaction act;
/* Upon receiving a SIGQUIT, this signal handler will be invoked */
void sighandler(int signum, siginfo_t *info, void *ptr) {
printf("Received signal: %d\n", signum);
printf("signal originate from pid[%d]\n", info->si_pid);
printf("Inside a signal handler...\n");
show_backtrace();
while(1)
;
printf("[FATAL] quiting the signal handler\n");
}
int main(int argc, char *argv[]) {
{
printf("Pid of the current process: %d\n", getpid());
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGQUIT, &act, NULL);
while(1)
;
return 0;
}
So you should run this program, and then send it a SIGQUIT. Upon receiving a
SIGQUIT, the signal handler will be invoked and the show_backtrace() function
will be called, which will unwind the stack and eventually find the signal
handler frame, reporting 1.
More interesting, libunwind allows you to detect "remotely" with its
libunwind-ptrace module. By "remotely", it simply means that you can use
ptrace(2) to attach to a process and then you can use libunwind-ptrace to
detect the remote process is running in a signal handler.
For more info, please refer to libunwind's doc
Is there any way to send a signal to a process (in Linux), that results in a termination of the process after going through the "atexit-functions" (in this case: void shutdownEngines())? Using "pkill name" does not work.
#include <cstdlib>
void shutdownEngines() {/*is not executed by "pkill name"*/}
int main() {
atexit(shutdownEngines);
while(true)
doStuff();
}
Usage: I'm currently programming a robot. Every time I want to test it, I'll start the program and terminate it with "pkill name", but "shutdownEngines" isn't called and the robot keeps moving, falling off the table etc.
I know I could do "pkill name; ./shutdownEngines.sh", but this would be very bad style in my case (the numbers of the gpio pins connected to the engines are defined in a header file of the main program (the source code of the main program is not on the robot but on my computer). Making sure that there's always a "shutdownEngines.sh" program/script with the right pins on every robot would be very complicated.
Update
The following code works perfectly:
#include <iostream>
#include <csignal>
#include <cstdlib>
void signalHandler(__attribute__((unused)) const int signum) {
exit(EXIT_FAILURE);
}
void driverEpilog() {
std::cout << "shutting down engines...";
//drv255(0,0);
}
int main() {
signal(SIGTERM, signalHandler);
atexit(driverEpilog);
while(true)
system("sleep 1");
}
from the man page of atexit:
Functions registered using atexit() (and on_exit(3)) are not called
if a process terminates abnormally because of the delivery of a
signal.
atexit is called when your main routine returns or when you call exit, not on a signal.
When you call pkill you're sending a SIGTERM signal. Handle this signal with signal or sigaction instead (define handlers on SIGTERM, SIGINT, SIGFPE, ...) to stop the engines before exiting your program.
Example lifted from GNU C library documentation:
void
termination_handler (int signum)
{
struct temp_file *p;
for (p = temp_file_list; p; p = p->next)
unlink (p->name); // don't delete files, stop your engines instead :)
}
int
main (void)
{
…
struct sigaction new_action, old_action;
/* Set up the structure to specify the new action. */
new_action.sa_handler = termination_handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGINT, &new_action, NULL);
sigaction (SIGHUP, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGHUP, &new_action, NULL);
sigaction (SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGTERM, &new_action, NULL);
…
}
(of course, no handler can handle the SIGKILL "signal", which tells the OS to remove your process from the active process list, without further notice!)
So I have a daemon who can be gracefully shut down using SIGQUIT.
This daemon is running boost::asio::io_service. I use boost::asio::signal_set to catch this signal.
I have encountered a behaviour that I believe to be completely wrong. When I destroy boost::asio::signal_set object it does not restore previous handler of that signal. Previous handler for SIGQUIT was a no-op. So upon receiving this signal after boost::asio::signal_set was destroyed my daemon terminates. My guess is this is because boost::asio::signal_set upon destruction sets default handler, that is to terminate the program, but not the previous handler.
I see this as very inappropriate. What I am asking is am I wrong? Maybe I am missing something?
Boost.Asio does not specify the resulting handler state for a signal that had been added to boost::asio::signal_set and then removed via either signal_set::remove(), signal_set::clear(), or destruction of the signal_set. In particular, the post-condition is not specified for any of the associated operations in the Signal Set Service requirements.
A quick glance a the signal_set_service::add() implementation:
::sigaction(signal_number, &sa, 0)
and the signal_set_service::clear() implementation:
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
::sigaction(reg->signal_number_, &sa, 0)
shows that the calls to sigaction() are not handling previously installed handlers, and results in the default handler action being registered when a signal is removed via signal_set_service.
As a signal may be delivered after Boost.Asio sets the signal action to default, but before the application code has been able to assign its own handler, consider using pthread_sigmask() to block all signals within the io_service. Once the signals have been removed from the signal_set, assign the desired handler via sigaction(), then unblock the signals.
Here is a complete example demonstrating this approach:
#include <iostream>
#include <boost/asio.hpp>
void signal_handler(int signal_number)
{
std::cout << "signal_handler(): " << signal_number << std::endl;
}
int main()
{
// Force scope to control io_service lifetime.
{
boost::asio::io_service io_service;
// Boost.Asio will register an internal handler for SIGQUIT.
boost::asio::signal_set signal_set(io_service, SIGQUIT);
signal_set.async_wait(
[](const boost::system::error_code& error,
int signal_number)
{
std::cout << "siganl_set.async_wait handler: "
<< signal_number << std::endl;
// Block SIGQUIT.
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGQUIT);
assert(pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) == 0);
});
// Send SIGQUIT to this process.
raise(SIGQUIT);
// By the time raise() returns, Boost.Asio has handled SIGQUIT 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.
// Prior to calling the io_service, SIGQUIT is not blocked.
io_service.run();
// The user provided handler was invoked and has blocked SIGQUIT.
}
// Send SIGQUIT to this process.
raise(SIGQUIT);
// Even though Boost.Asio has set the default handler for SIGQUIT, the
// signal is blocked, so the signal has been placed into a pending state.
// Register a custom handler for SIGQUIT.
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = &signal_handler;
assert(sigaction(SIGQUIT, &sa, 0) == 0);
// Unblock SIGQUIT.
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGQUIT);
assert(pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL) == 0);
// Upon unblocking, the pending SIGQUIT signal is delivered and handled
// by the handler registered via sigaction.
std::cout << "Fin" << std::endl;
}
And its output:
$ ./a.out
siganl_set.async_wait handler: 3
signal_handler(): 3
Fin
My application has two threads. Each threads recevive some data from the server via each sockets. Threads wait to return epoll_wait(). Sometimes epoll_wait() returns -1 and errno is EINTR. EINTR means that system call() is interrupted by a signal. I added to process EINTR.
However I do not know what a signal is arrived and why a signal is arrived. I wonder it.
Method 1.
I created a thread.
sigset_t sMaskOfSignal;
sigset_t sOldMaskOfSignal;
sigfillset(&sMaskOfSignal);
sigprocmask(SIG_UNBLOCK, &sMaskOfSignal, &sOldMaskOfSignal)
while(1)
{
sigwait(&sMaskOfSignal, &sArrivedSignal);
fprintf(stdout, "%d(%s) signal caught\n", sArrivedSignal, strsignal(sArrivedSignal));
}
I could not catch a signal when epoll_wait() is interrupted.
Method 2
When I execute my application in strace tool, epoll_wait() never be interrupted.
My problem is reproduced very well in GDB tool. I need helps....
You can try to implement your own signal handler. If you application gets interrupted by a signal again, your own signal-handler will be called and you can see, what kind of signal has been raised.
void
signal_callback_handler(int signum)
{
printf("Caught signal %d\n",signum);
exit(signum); // terminate application
}
int main()
{
// Register signal handler for all signals you want to handle
signal(SIGINT, signal_callback_handler);
signal(SIGABRT, signal_callback_handler);
signal(SIGSEGV, signal_callback_handler);
// .. and even more, if you want to
}
Not a very handy-method, but this should (hopefully) enable you to find out, what signal has been raised. Take a look here to see the different signals, that can be handled (note: not all signals can be handled in your own signal-handler(!)).
May be you should try setting signal handler for catching all signals and set your signal flags to SA_SIGINFO
something like this
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = <handler>;
sigaction(SIGFPE, &act, 0);
sigaction(SIGHUP, &act, 0);
sigaction(SIGABRT, &act, 0);
sigaction(SIGILL, &act, 0);
sigaction(SIGALRM, &act, 0);
sigaction(SIGALRM, &act, 0);
.
.
.
//and your handler looks like
void handle_sig (int sig, siginfo_t *info, void *ptr)
{
printf ("Signal is %d\n",sig);
}
Resgister the handler in your main program and ignore EINTR in epoll.