with reference to this, I have included two timers (it_val1, it_val) in setTimer() in my program as below:
void stepRoutingTable(){
}
void incrementCounter(){
}
void setTimer(){
struct itimerval it_val1;
if (signal(SIGALRM, (void (*)(int)) incrementCounter) == SIG_ERR) {
cerr<<"Unable to catch SIGALRM"<<endl;
exit(1);
}
it_val1.it_value.tv_sec = updateInterval;
it_val1.it_value.tv_usec = (updateInterval) % 1000000;
it_val1.it_interval = it_val1.it_value;
if (setitimer(ITIMER_REAL, &it_val1, NULL) == -1) {
cerr<<"error calling setitimer()";
exit(1);
}
struct itimerval it_val;
if (signal(SIGALRM, (void (*)(int)) stepRoutingTable) == SIG_ERR) {
cerr<<"Unable to catch SIGALRM"<<endl;
exit(1);
}
it_val.it_value.tv_sec = updateInterval;
it_val.it_value.tv_usec = (updateInterval) % 1000000;
it_val.it_interval = it_val.it_value;
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
cerr<<"error calling setitimer()";
exit(1);
}
return;
}
int main(int argc, char* ipCmd[]){
updateInterval=100;
setTimer();
}
But only it_val is triggered upon execution and not it_val1, what could be the error?
There's only one SIGALARM signal handler, and only one ITIMER_REAL timer.
Installing a handler for a SIGALARM removes the previous signal handler, and replaces it with a new one.
Setting the ITIMER_REAL timer clears any previously set timer, and replaces it with a new one.
The shown code sets the SIGALARM handler, and sets the ITIMER_REAL timer. Then, the shown does this again.
The final result is that only the second timer and signal handler remains in effect. There's only one ITIMER_REAL timer, and when it expires, as described, a SIGALARM signal is generated, and whatever signal handler that's installed at that time, is the one that will be invoked.
If you need to implement a framework for multiple timeouts, with a signal handler for each one, you will have to write this framework yourself, in terms of a single timer, and a single signal handler.
Related
The application is multi-threaded.
Inside main(), I register the signal handler for SIGUSR1:
// Global variable to indicate whether directory's
// content needs to be reloaded
bool reload_dir = 0;
int main (int argc, char *argv[])
{
...
signal(SIGUSR1, sigusr1_handler);
...
RunServer(arg1, ...);
return 0;
}
Signal handler:
static void
sigusr1_handler (int signo __unused)
{
reload_dir = 1;
return;
}
The following function (which is called from main) is only executed by the main thread:
void
RunServer (arg1, ...)
{
// do some stuffs
...
while (cond != true) {
sleep(1);
}
server_exit();
}
Now, when the SIGUSR1 is caught (by any thread including the main thread), I'm setting the reload_dir variable to 1. And in RunServer(), I'm reloading the directory based on that value. However, I'm also resetting the global variable reload_dir to 0 to avoid loading the directory repeatedly indefinitely. And this setting reload_dir to 0 will introduce a race.
Since we should not use locks or mutex in a signal handler, how can I achieve this without majorly changing the existing application design.
void
RunServer (arg1, ...)
{
// do some stuffs
...
while (cond != true) {
if (reload_dir) {
// reset reload_dir to avoid loading repeatedly indefinitely
reload_dir = 0; // Race condition?
dir_reinit();
}
sleep(1);
}
server_exit();
}
Block SIGUSR1 with pthread_sigmask before any threads are spawned, so that all threads inherit that mask. Then, in main(), use sigtimedwait instead of sleep in your main loop to check if USR1 has been delivered.
int main(...) {
...
sigset_t ss_usr1;
sigemptyset(&ss_usr1);
sigaddset(&ss_usr1, SIGUSR1);
// block SIGUSR1
pthread_sigmask(SIG_BLOCK, &ss_usr1, NULL);
... spawn threads ...
// RunServer
struct timespec patience = { .tv_sec = 1 };
while (! some_condition) {
int s = sigtimedwait(&ss_usr1, NULL, &patience);
if (s == SIGUSR1) dir_reinit();
// handle errors other than timeout appropriately
}
server_exit();
...
}
Benefits: no signal handler complexity (and you won't be chastized, rightly, for using signal instead of the superior sigaction; no need for atomic flags or sig_atomic_t; easier to reason about behavior.
I've made a Node addon using AsyncProgressWorker thread to handle my socket messages. Here is my code:
class ProgressWorker : public AsyncProgressWorker {
public:
ProgressWorker(
Callback *callback
, Callback *progress)
: AsyncProgressWorker(callback), progress(progress) {}
~ProgressWorker() {}
void Execute (const AsyncProgressWorker::ExecutionProgress& progress) {
char response[4096];
int result;
int connected = 1;
int timeout = 0;
int pending = 0;
while(connected) {
result = sctp_recvmsg(sock, (void *)&response, (size_t)sizeof(response), NULL, 0, 0, 0);
if (result > 0 && result < 4095) {
if (debug) {
printf("Server replied (size %d)\n", result);
}
pending = 0;
progress.Send((const char *)response, size_t(result));
result = 0;
}
else {
// Don't mind my timeout mechanism. :))
if ((result == -1 && errno != EWOULDBLOCK) || pending) {
if (timeout == 0) {
printf("Can't receive from other end. Waiting for 3 seconds. Error code: %d\n", errno);
pending = 1;
}
if (timeout >= 3000) {
connected = 0;
close(sock);
}
else {
timeout += 5;
usleep(5000);
}
}
else {
usleep(5000);
}
}
}
}
void HandleProgressCallback(const char *data, size_t count) {
HandleScope scope;
v8::Local<v8::Value> argv[] = {
CopyBuffer(const_cast<char*>(data), count).ToLocalChecked()
};
progress->Call(1, argv); // This is the callback to nodejs
}
private:
Callback *progress;
};
Now I haven't stress-tested this until tonight then I noticed that some messages won't make it back to node. It will print my "Server replied" debug log but won't log my debug logs I put on the progress callback. Am I missing something here? Thanks in advance.
AsyncProgressWorker is based on a uv_async_t, which allows any thread to wake the main thread. However, as stated in the documentation:
libuv will coalesce calls to uv_async_send(), that is, not every call
to it will yield an execution of the callback. For example: if
uv_async_send() is called 5 times in a row before the callback is
called, the callback will only be called once. If uv_async_send() is
called again after the callback was called, it will be called again.
^^ This is the reason that you may sometimes not receive some events while your application is under stress. Above this line is the answer to the question. Below is my "above and beyond" possible solution to deal with your problem:
It so happens that I am working on adding a new alternative to AsyncProgressWorker that promises to deliver every event, just as AsyncProgressWorker does, but using a queue. This feature was recently merged into NAN. If you want to test it, try out the git repository at https://github.com/nodejs/nan , and then replace your AsyncProgressWorker with AsyncProgressQueueWorker<char> Re-run your tests and all events will be delivered.
The pull request to add this new feature is here: https://github.com/nodejs/nan/pull/692 - merged on Oct 6, 2017.
This new feature was released in NAN version 2.8.0
You can use this new class template by altering your package.json to use nan version 2.8.0 or later:
"dependencies": {
"nan": "^2.8.0"
},
Consider the next piece of code:
// Sigaction and timers
struct sigaction sa;
sigset_t maskSet, pendingSet;
/**
* Blocks the SIG_SETMASK in maskSet.
* #return None.
*/
static void block_signal(void)
{
// ~~~Blocking signal~~~
if(sigemptyset(&pendingSet) == -1)
{
ErrorHandler::sysCallError(THREAD_SYS_CALL_ERROR_SIGNAL_HANDLE);
}
if(sigpending(&pendingSet) == -1)
{
ErrorHandler::sysCallError(THREAD_SYS_CALL_ERROR_SIGNAL_HANDLE);
}
if(sigprocmask(SIG_BLOCK, &maskSet, NULL) == -1)
{
killProcessAfterMemoryAllocs();
}
}
/**
* Unblocks the SIG_SETMASK in maskSet.
* #return None.
*/
static void unblock_signal(void)
{
// ~~~Blocking signal~~~
int result;
int sig;
// If we got a signal while performing operation that require signal block.
if(sigismember(&pendingSet, SIGVTALRM) != -1)
{
result = sigwait(&pendingSet, &sig);
// DOESNT REACH HERE
if(result == 0)
{
printf("sigwait() returned for signal %d\n", sig);
//Do stuff
}
}
if (sigprocmask(SIG_UNBLOCK, &maskSet, NULL) == -1)
{
killProcessAfterMemoryAllocs();
}
}
My main goal is to be able to run functions, that during their run - SIGVTALARM ,that is raised by a timer i defined, will be blocked. (block_signal -> dosomthing SIGNALS ARE BLOCKED -> unblocksignal). Maskset is initialized with SIGVTALARM
Two questions:
By the way i implemented, result = sigwait(&pendingSet, &sig); causes the program go into an infinite loop.
Without sigwait() - I use a virtual timer that raise SIGVTALARM every defined interval of time.
Suppose i blocked SIGVTALARM. I understand that, as soon (while blocked) as it is raised - the signal becomes pending. And as soon as i unblock it, the signal is recieved and treated by a signal hanler.
What i dont understand is whats going on with the NEXT signal raised. Will the next signal will be raised a defined interval of time after the PREVIOUS signal released, or will it be raised a defined interval of time from the moment the PREVIOUS signal raised (and blocked -> became pending).
I have started a timer and set the interval as 5 secs and registered a signal handler for it.
When SIGALRM is encountered iam trying to terminate the thread inside the signal handler, bt not able to do that. Thread is not getting terminated , instead of this whole process is killed.
The following is the code:
void signalHandler()
{
printf("Caught signal ...\n");
printf("Now going to terminate thread..\n");
pthread_kill(tid, SIGKILL);
}
void * thread_function()
{
int oldstate;
char result[256] = {0};
time_t startTime = time(NULL);
time_t timerDuration = 5;
time_t endTime = startTime + timerDuration;
while(1) {
printf("Timer is runnuing as dameon..\n");
if(!strcmp(result, "CONNECTED")) {
resp = 1;
pthread_exit(&resp);
}
}
}
int main()
{
int *ptr[2];
signal(SIGALRM, signalHandler);
timer.it_interval.tv_usec = 0;
timer.it_interval. tv_usec = 0;
timer.it_value.tv_sec = INTERVAL;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, 0);
pthread_create(&tid, NULL, thread_function, NULL);
pthread_join(tid, (void**)&(ptr[0]));
printf("test %d\n\n",*ptr[0]);
while(1)
printf("1");
}
Platform : Linux , gcc compiler
As far as I'm aware you pretty much can't call anything inside a signal handler as you don't know what state your code is in.
Your best option is to set up a thread to handle your signals. All your other threads should call pthread_setsigmask and to block all signals, and then you create another thread, which calls calls pthread_setsigmask to catch SIGALARM, and then calls sigwait, at which point it can cancel the other thread.
The way of handling signals is much different in a multi-threaded environment as compared to a single threaded environment. In a multi-threaded code, you should block out all the signals for all the threads that have your business logic and then create a seperate thread for handling the signals. This is because, in multi-threaded environment, you cannot be sure to which thread the signal will be delivered.
Please refer to this link for more details:
http://devcry.heiho.net/2009/05/pthreads-and-unix-signals.html
Apart from this, to kill a thread use pthread_cancel which should work fine for you.
You can try using a flag:
int go_on[number_of_threads] = { 1 };
void signalHandler()
{
printf("Caught signal ...\n");
printf("Now going to terminate thread..\n");
go_on[tid] = 0;
}
void * thread_function()
{ /* */
while(go_on[this_thread_id]) {
printf("Timer is runnuing as dameon..\n");
if(!strcmp(result, "CONNECTED")) {
resp = 1;
pthread_exit(&resp);
}
}
}
I am writing program in c++ which runs GNU readline in separate thread. When main thread is exited I need to finish the thread in which readline() function is called. The readline() function is returned only when standart input came (enter pressed).
Is there any way to send input to application or explicitly return from readline function?
Thanks in advance.
Instead of returning from main thread, call exit(errno). All other threads will be killed nastily!
Or, if you wanted to be nicer, and depending on your OS, you could send a signal to the readline thread, which would interrupt the syscall.
Or, if you wanted to be cleverer, you could run readline in async mode, using a select() loop with a timeout so that your thread never blocks in readine functions, and your thread can clean up after itself.
I experimented with this situation as well. I thought perhaps one could call close(STDIN_FILENO), which does cause readline to return on the other thread, but for some reason it leaves the terminal in a bad state (doesn't echo characters so you can't see what you're typing). However, a call to the 'reset' command will fix this, so the full alternative is:
close(STDIN_FILENO);
pthread_join(...); // or whatever to wait for thread exit
system("reset -Q"); // -Q to avoid displaying cruft
However, the final better solution I used, inspired by the other suggestions, was to override rl_getc:
rl_getc_function = getc; // stdio's getc passes
and then you can use pthread_kill() to send a signal to interrupt the getc, which returns a -1 to readline, which returns a NULL to the calling thread so you can exit cleanly instead of looping for the next input (the same as would happen if the user EOF'd by ctrl-D)
Now you can have your cake (easy blocking readlines) and eat it too (be able to stop by external event without screwing up the terminal)
C++ standard input is not designed to be thread safe. So, even if there was a method to programatically stop it from waiting input, you wouldn't be able to call it from another thread. Of course, there could be an implementation specific way to do so.
Old thread but still readline API seems not explored.
In order to interrupt readline first I disabled readline signal handlers.
Do not look at the ugly global_buffer I'm using - it's just an example
http://www.delorie.com/gnu/docs/readline/rlman_43.html
Reader Thread:
pthread_mutex_t lock;
int isBufferReady = 0;
char global_buffer[2500]; /// Assuming that reads will not be any bigger
void *reader_thread(void *arg)
{
rl_getc_function = getc;
rl_catch_signals = 0;
rl_catch_sigwinch = 0;
char *input;
while ( (input = readline( NULL )) )
{
i = strlen(input)-1;
if ( input[i] == '\0' )
return NULL;
/// Due to TAB there might be a whitespace in the end
while ( i > 0 )
{
if ( isspace(input[i]) )
{
input[i] = '\0';
}
else
{
break;
}
i--;
}
pthread_mutex_lock(&lock);
read_file_function( input, buffer );
free(input);
isBufferReady = 1;
pthread_mutex_unlock(&lock);
}
printf( "Im closed \n" );
return NULL;
}
Signal handler:
volatile int keepRunning = 1;
void SIG_handler(int signal)
{
int static sig_count = 0;
switch ( signal )
{
case SIGUSR2:
{
/// Yeah I know I should not printf in a signal handler
printf( "USR2: %d \n", sig_count++);
break;
}
default:
{
printf( " SIGHANDLE\n" );
keepRunning = 0;
break;
}
}
}
main:
int main( int argc, char *argv[] )
{
pthread_t file_reader;
{ /// Signal Handler registration
struct sigaction sigact = {{0}};
sigact.sa_handler = SIG_handler;
// sigact.sa_flags = SA_RESTART;
sigaction(SIGINT , &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGHUP, &sigact, NULL);
// sigaction(SIGUSR1, &sigact, NULL);
sigaction(SIGUSR2, &sigact, NULL);
}
pthread_create( &file_reader, NULL, reader_thread, NULL );
while(keepRunning)
{
pthread_mutex_lock(&lock);
if( !isBufferReady )
{
... fill in global_buffer according to some algorithm
}
pthread_mutex_unlock(&lock);
usleep(10);
pthread_mutex_lock(&lock);
if(isBufferReady)
isBufferReady = 0;
... some operation on the 'global_buffer' like write its contents to socket
pthread_mutex_unlock(&lock);
usleep(10);
}
signal(SIGINT, SIG_DFL);
pthread_cancel( file_reader );
pthread_join( file_reader, NULL);
pthread_mutex_destroy(&lock);
rl_cleanup_after_signal();
return 0;
}
With this (nowhere near perfect) code snippet I was able to finally interrupt readline without described prevously flakiness.
Used this code snippet for interactive debug purposes where I had prepared packets in simple text files and read-in those files with the help of readline.