C++ (under Linux) program not giving expected output ( timer ) - c++

I have this C++ program. It has a simple for loop which prints numbers from 1 to 20. Between this, execution, the timer expires multiple times, and each time it expires, it should print an output from signal handler.
Unfortunately i am not getting this output. And it is just simply printing the numbers from 1 to 20. Can someone please help me?
Thanks in advance
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
#include <iostream>
using namespace std;
static int flag=0;
class timer{
static void
handler(int sig) {
printf("Caught signal %d\n", sig);
::flag=1;
signal(sig, handler);
}
public:
void timer_func()
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs=1; // The timer frequency in nanosecs
sigset_t mask;
struct sigaction sa;
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIG);
sa.sa_flags = SA_RESETHAND;
sa.sa_handler = handler;
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCKID, &sev, &timerid) == -1)
errExit("timer_create");
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
its.it_value.tv_sec = freq_nanosecs / 1000000000;
its.it_value.tv_nsec = freq_nanosecs % 1000000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime(timerid, 0, &its, NULL) == -1)
errExit("timer_settime");
}
};
int main() {
timer ob;
ob.timer_func();
for(int i=0; i<20; i++) {
sleep(1);
if(flag) {
cout << "Timer called" << endl;
flag=0;
}
cout << "Printing i: " << i << endl;
}
}
But if i set "long long freq_nanosecs = 1" in that also the output is only once from the timer. It should be repeated

0.011 is a double literal, you assign it to a long, so it's converted to 0. This simply sets freq_nanosecs to 0.
long freq_nanosecs=0.011
This disarms the timer since the timer values are 0.
timer_settime(timerid, 0, &its, NULL)

First things first: please do not use signal(2) to install signal handlers. Use sigaction(2) instead; signal(2) is unreliable and very unportable.
Next, you're trying to use printf(3) inside a signal handler. printf(3) is not a signal-safe function. The only "standard" functions you are allowed to use inside a signal handler are listed in signal(7). (You can also call your own functions, iff they only call functions listed in signal(7) or do very simple operations, such as setting a flag to indicate that a signal has occured.)

The signal handler is not installed. Call sigaction function as follows:
sa.sa_flags = SA_RESETHAND;
sa.sa_handler = handler;
sigaction(SIG, &sa, NULL);
The sa_flags SA_RESETHAND (man sigaction)
Restore the signal action to the default state once the signal handler has been called
And (man 7 signal)
The default action for an unhandled real-time signal is to terminate
the receiving process.
Before print, next real-time signal received, and exit the program.
Please set the sa_flags to zero.

Related

Multithreaded timer class

I've created a timer class that performs a user supplied action (function that takes no arguments has no return type) at a user supplied interval. This action should be performed in its own thread--i.e. when the timer is created, a new thread is created, and that thread consists of a loop that uses sigwait to wait for the signal to come in before performing the callback. The signal I want to use will be anywhere from SIGRTMIN to SIGRTMAX. I want to be able to create multiple timer objects which means multiple threads and multiple signals (one thread and signal per timer). Using this post, the timer_create man page, and pthread_sigmask man page as references, this is what I have:
//timer.h
#ifndef TIMERS_H
#define TIMERS_H
#include <signal.h>
#include <time.h>
#include <inttypes.h>
#include <stdio.h>
#include <pthread.h>
class CTimer
{
public:
CTimer(uint64_t period_ms, void(*callback)(void), int sig );
private:
typedef void (*Callback)(void);
Callback m_pCallback;
timer_t timerID;
struct sigevent sev;
struct itimerspec its;
struct sigaction sa;
uint8_t timerNum;
pthread_t thread_id;
sigset_t set;
int signal_ID;
void* loop();
friend void* run_loop(void* arg);
};
#endif // TIMERS_H
and
//timer.cpp
#include "timers.h"
void* run_loop(void* arg)
{
return static_cast<CTimer*>(arg)->loop();
}
CTimer::CTimer(uint64_t period_ms, void(*callback)(void), int sig):
m_pCallback(callback), signal_ID(sig)
{
//create mask to send appropriate signal to thread
int s;
sigemptyset(&set);
s = sigaddset(&set, signal_ID);
if (s != 0)
{
printf("error on sigaddset\n");
}
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
{
printf("error on pthread_sigmask\n");
}
//create new thread that will run the signal handler
s = pthread_create(&thread_id, NULL, run_loop, this);
if (s != 0)
{
printf("error on pthread_create\n");
}
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = signal_ID;
sev.sigev_value.sival_ptr = &timerID;
if (timer_create(CLOCK_REALTIME, &sev, &timerID) == -1)
{
printf("error on timer create\n");
}
its.it_value.tv_sec = period_ms / 1000;
its.it_value.tv_nsec = period_ms % 1000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime(timerID, 0, &its, NULL) == -1)
{
printf("error on timer settime\n");
}
}
void* CTimer::loop()
{
int s = 0;
while (1)
{
s = sigwait(&set, &signal_ID);
m_pCallback();
}
}
For testing I am using this:
//driver.cpp
#include <stdio.h>
#include <unistd.h>
#include "sys/time.h"
#include "timers.h"
uint64_t get_time_usec()
{
static struct timeval _time_stamp;
gettimeofday(&_time_stamp, NULL);
return _time_stamp.tv_sec*1000000 + _time_stamp.tv_usec;
}
void callbacktest1()
{
printf("tick1 %" PRIu64 " \n", get_time_usec());
}
void callbacktest2()
{
printf("tick2 %" PRIu64 " \n", get_time_usec());
}
int main(int argv, char *argc[])
{
CTimer t1(1000, callbacktest1, SIGRTMIN);
CTimer t2(2000, callbacktest2, SIGRTMIN+1);
pause();
}
When running, it will crash pretty quickly with the error "Real-time signal 1". If I run it in gdb, I get
Starting program: /home/overlord/MySource/Timer/driver
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff75ee700 (LWP 21455)]
[New Thread 0x7ffff6ded700 (LWP 21456)]
tick1 1477336403700925
tick1 1477336404700920
Program received signal SIG35, Real-time event 35.
[Switching to Thread 0x7ffff75ee700 (LWP 21455)]
0x00007ffff7bcc0c1 in do_sigwait (sig=0x7fffffffdbc8, set=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/../../../../../sysdeps/unix/sysv/linux/sigwait.c:60
60 ../nptl/sysdeps/unix/sysv/linux/../../../../../sysdeps/unix/sysv/linux/sigwait.c: No such file or directory.
which is interesting because 35 is what SIGRTMIN+1 is equal to. So maybe I'm not routing the signals correctly? If I only create once instance of the timer in the driver.cpp file, things appear to work ok. Any thoughts are appreciated.
I'm also curious if this is even the right approach to what I'm trying to do. In some brief tests I did, using the system signals seems way more stable than using sleep and usleep to burn up unused loop time.
My guess is that the signal used to wake second thread (CTimer t2) is not blocked by the first thread (CTimer t1). Signal mask in a thread is inherited from a parent thread, so when you start first thread it only has SIGRTMIN signal blocked, but SIGRTMIN+1 can still be delivered to it. Standard reaction to real-time signals is to terminate process, this is what happens. You can test this theory by blocking all real-time signals in all threads started by CTimer class.
I'm not sure why you think that sleep/usleep is less reliable than your own solution, using the right patterns with usleep (basically expecting that it can return sooner and waiting in a loop) always worked OK for me.
I'm not sure why you think that sleep/usleep is less reliable than
your own solution, using the right patterns with usleep (basically
expecting that it can return sooner and waiting in a loop) always
worked OK for me.
I did a basic test using the following code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>
#include <math.h>
#define CLOCKID CLOCK_REALTIME
#define SIG SIGRTMIN
#define SQ(x) ((x)*(x))
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
uint64_t start_time_us = 0;
double error_ms = 0;
int64_t count = 0;
int64_t last_time_us = 0;
uint64_t period_ns;
uint64_t get_time_usec()
{
static struct timeval _time_stamp;
gettimeofday(&_time_stamp, NULL);
return _time_stamp.tv_sec*1000000 + _time_stamp.tv_usec;
}
static void
handler(int sig, siginfo_t *si, void *uc)
{
uint64_t timestamp_us = get_time_usec();
double dt_ms = (double)(timestamp_us - last_time_us)/1000;
double elapsed_ms = (double)(timestamp_us - start_time_us)/1000;
error_ms += SQ((dt_ms - (double)period_ns/1000000.0));
count++;
last_time_us = timestamp_us;
}
namespace hidi
{
void pause(const double& tSeconds)
{
unsigned int decimal = static_cast<unsigned int>(floor(tSeconds));
double fraction = tSeconds-static_cast<double>(decimal);
if (decimal > 0)
sleep(decimal);
usleep(static_cast<unsigned long>(floor(fraction*1000000.0)));
return;
}
}
int
main(int argc, char *argv[])
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
//sigset_t mask;
struct sigaction sa;
if (argc != 3) {
fprintf(stderr, "Usage: %s <test length-secs> <period-millisec>\n",
argv[0]);
exit(EXIT_FAILURE);
}
uint64_t period_ms = atoll(argv[2]);
period_ns = period_ms * 1000000;
/// FIRST TEST LOOP RATE STABILITY USING THE TIMER
// THE TIMER WILL USE SIGRTMIN (DEFINED ABOVE) AND WILL MEASURE
// STATISTICS ON LOOP STABILITY
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIG);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
errExit("sigaction");
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCKID, &sev, &timerid) == -1)
errExit("timer_create");
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
printf("Timing period is %zu ms\n", period_ms);
its.it_value.tv_sec = period_ns / 1000000000;
its.it_value.tv_nsec = period_ns % 1000000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime(timerid, 0, &its, NULL) == -1)
errExit("timer_settime");
start_time_us = last_time_us = get_time_usec();
printf("Sleeping for %d seconds\n", atoi(argv[1]));
while ((get_time_usec()-start_time_us)/1000000 < atoi(argv[1]))
{
sleep(1); //this just prevents the while loop from spinning out of control
// the sleep function is interrupted with the signal callback is
// executed. All the magic happens in the callback.
}
printf("ave error: %8.6f ms %zu samples\n",sqrt((double)error_ms/(double)count), count);
timer_delete(timerid); // disarm / delete timer
/// START TEST USING SLEEP / USLEEP
start_time_us = last_time_us = get_time_usec();
error_ms = count = 0;
while ((get_time_usec()-start_time_us)/1000000 < atoi(argv[1]))
{
uint64_t timestamp_us = get_time_usec();
double dt_ms = (double)(timestamp_us - last_time_us)/1000;
double elapsed_ms = (double)(timestamp_us - start_time_us)/1000;
error_ms += SQ((dt_ms - (double)period_ns/1000000.0));
//printf("et=%8.6f ms, dt=%8.6f ms ave error %f\n", elapsed_ms, dt_ms, error_ms/count);
count++;
last_time_us = timestamp_us;
uint64_t consumed_time_us = get_time_usec()-timestamp_us;
uint64_t remaining_looptime_us = (period_ns/1000) - consumed_time_us;
hidi::pause((double)remaining_looptime_us/1000000.0);
}
printf("ave error: %8.6f ms %zu samples\n",sqrt((double)error_ms/(double)count), count);
exit(EXIT_SUCCESS);
}
testing periods from 10 ms to 2 seconds, using timers just seemed way more stable. It seemed using the sleep/usleep method the error was proportional to the period i.e. it was 2-3 ms for a 10 ms period, but 300 - 400 ms for a 1000 ms period. using the timer, the error was pretty constant with different periods.

setitimer signalling seems only to work after fork

I would like to use the following C++ code to wait for a predefined amount of time (in this example always 2 seconds), but still be interruptible by a signal (that's why I don't use sleep):
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <iostream>
using namespace std;
int measure() {
itimerval idle;
sigset_t sigset;
int sig;
idle.it_value.tv_sec = 2;
idle.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &idle, NULL); // TODO: check return value
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM); // TODO return values
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL); // TODO return value?
sigwait(&sigset, &sig); // TODO check return value
while(sig != SIGUSR1) {
cout << "Hohoho" << endl;
idle.it_value.tv_sec = 2;
idle.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &idle, NULL); // TODO: check return value
sigwait(&sigset, &sig); // TODO check return value
}
cout << "Done with measurements." << endl;
return 0;
}
int main(int argc, char **argv) {
//if(fork() != 0) exit(0);
//if(fork() == 0) exit(0);
return measure();
}
I would expect this code to print "Hohoho" every 2 seconds until it receives SIGUSR1. Then it prints "Done with measurements." and exits. The second part works as expected. However, I see no "Hohoho", so it seems to me that the SIGALRM from setitimer somehow is not received. The strange thing is that if I do a fork before, the program works as expected. More specifically, if I uncomment either one of the two fork commands at the end, it works. Hence it does not depend on if it's the parent or child process, but somehow the fork event matters. Can someone explain to me what's going on and how to fix my code?
Thanks a lot,
Lutz
(1) Your setitimer is failing because you haven't set it correctly. Struct itimerval contains two structs of type timeval. You are only setting one and thereby picking up whatever garbage was in local storage when idle was declared.
struct itimerval {
struct timeval it_interval; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
If you want a repeating timer every 2 seconds then set the 2nd set to repeat with the same values.
idle.it_value.tv_sec = 2;
idle.it_value.tv_usec = 0;
idle.it_interval.tv_sec = 2;
idle.it_interval.tv_usec = 0;

how to solve the linux timer signal handler

why is not possible to have a multiple timer with single handler. I used the program from the below link and it is not working. He has explained the reason about the problem but it is not very clear. Is someone help me why is it not working ??
http://www.graphics-muse.org/wp/?p=868
There is no reason you can't have multiple timers created with timer_create using the same handler, provided your sigval structure contains enough information to distinguish between them as needed in your handler.
The point of the article is that it is possible to have multiple timers trigger the same handler but you need to differentiate them based on some passed data. Oddly the example the author used only went 3/4th of the distance of illustrating this in the code so maybe that is the source of your confusion.
Hopefully this reworking of the article's program is a bit clearer. It uses the sival_ptr to point to a string but it can point to any type. This is how the timers are differentiated.
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
void timerHandler( int sig, siginfo_t *si, void *uc )
{
// obligator caution not to use printf and other async-unsafe calls
// in a handler in real programs
printf("I am timer %s\n", (char *) si->si_value.sival_ptr);
}
void makeTimer(char *name, int intervalMS)
{
struct sigevent te;
struct itimerspec its;
struct sigaction sa;
int sigNo = SIGRTMIN;
// Set up signal handler.
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timerHandler;
sigemptyset(&sa.sa_mask);
if (sigaction(sigNo, &sa, NULL) == -1)
errExit("sigaction");
// Set up timer
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = sigNo;
te.sigev_value.sival_ptr = name;
timer_t timerID;
if (timer_create(CLOCK_REALTIME, &te, &timerID) == -1)
errExit("timer_create");
its.it_value.tv_sec = intervalMS;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerID, 0, &its, NULL) == -1)
errExit("timer_settime");
return;
}
int main(int argc, char *argv[])
{
char *arr[3] = {"number one", "number two", "number three"};
makeTimer(arr[0], 1);
makeTimer(arr[1], 2);
makeTimer(arr[2], 3);
while (sleep(5));
return(0);
}

End two alarm signals in Unix and count SIGINT

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
using namespace std;
int count = 0;
void alarm2(int signo)
{
cout << count;
}
void alarm1(int signo)
{
signal(SIGALRM, alarm2);
cout << "ctrl+C";
alarm(10);
sleep(10);
}
int main()
{
signal(SIGALRM, alarm1);
alarm(3);
sleep(5);
}
I want that after 3 seconds I get the message "ctrl+C" and then another alarm set for 10 seconds; after that I should get the value of count. But when I run after just 10 sec I get "ctrl+C" and the value of count.
In your example you made many, many mistakes.
First of all look at documentation about which function is safe to call from
signal handlers:
https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
Of course functions that can allocate memory is not safe to call, because of it is not safe to call malloc.
Because of it is not right to call printf or std::ostream::opeartor<< (std::cout <<) in signal handler.
Second, in documentation (type man 3 sleep) clearly written it is not safe mix sleep and alarm,
Third you not wait enough in main function, so it can exit before the second alarm handler run.
Here is how it can be done:
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
volatile sig_atomic_t done = 0;
void alarm2(int signo)
{
write(STDOUT_FILENO, "alarm2\n", sizeof("alarm2\n") - 1);
done = 1;
}
void alarm1(int signo)
{
signal(SIGALRM, alarm2);
write(STDOUT_FILENO, "ctrl+C\n", sizeof("ctrl+C\n") - 1);
alarm(10);
}
int main()
{
signal(SIGALRM, alarm1);
alarm(3);
while (done == 0)
sleep(1); //sleep can be wake up by alarm signal, so check flag
}
Add "<< endl;" to all your cout statements and try again.

Deadlock with sigsuspend()

I am trying to synchronize a father and children, the following code is not working (apparently usr_interrupt++ is not atomic). Semaphores does not seems to help either.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <string>
#include <semaphore.h>
#include <fcntl.h>
using namespace std;
/* When a SIGUSR1 signal arrives, set this variable. */
volatile sig_atomic_t usr_interrupt;
sem_t *mutex;
char* SEM_NAME;
void
synch_signal (int sig)
{
// sem_wait(mutex);
usr_interrupt++;
// sem_post(mutex);
}
/* The child process executes this function. */
void
child_function (void)
{
/* Perform initialization. */
cerr << "I'm here!!! My pid is " << (int)getpid() << " my usr_int=" << usr_interrupt << endl;
/* Let parent know you're done. */
kill (getppid (), SIGUSR1);
/* Continue with execution. */
cerr << "Bye, now...." << endl;
exit(0);
}
int
main (void)
{
usr_interrupt = 0;
string s_sem_name = "lir";
SEM_NAME = new char[s_sem_name.size()+1];
memcpy(SEM_NAME, s_sem_name.c_str(), s_sem_name.size());
SEM_NAME[s_sem_name.size()] = '\0';
mutex = sem_open (SEM_NAME,O_CREAT,0644,1);
if(mutex == SEM_FAILED) {
perror("unable to create semaphore");
sem_unlink(SEM_NAME);
exit(-1);
}
struct sigaction usr_action;
sigset_t mask, oldmask;
pid_t child_id, child_id2;
/* Set up the mask of signals to temporarily block. */
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);
/* Establish the signal handler.*/
usr_action.sa_handler = synch_signal;
usr_action.sa_flags = 0;
sigaction (SIGUSR1, &usr_action, NULL);
/* Create the 2 children processes. */
child_id = fork ();
if (child_id == 0)
child_function ();
child_id2 = fork();
if (child_id2 == 0)
child_function ();
/* Wait for a signal to arrive. */
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (usr_interrupt != 2) {
sigsuspend (&oldmask);
}
sigprocmask (SIG_UNBLOCK, &mask, NULL);
/* Now continue execution. */
puts ("That's all, folks!");
return 0;
}
Can anyone suggest a fix? (I cannot use threads)
Best,
-- Liron
You can't count signals. Two signals of the same type has the same semantic meaning as one signal of that type. You could use two different signal types like USR1 and USR2. But honestly, you shouldn't use signals as a communication mechanism. Use something sensible like a pipe.