Multithreaded timer class - c++

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.

Related

Pthreads pool, keeping 1000 opened threads, pthread_create() returns 11

Need some help with PTHREADS. I want to keep over 1000 threads opened at any time, something like a thread pool. Here is the code :
/*
gcc -o test2 test2.cpp -static -lpthread -lstdc++
*/
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <stdexcept>
#include <cstdlib>
int NUM_THREADS = 2000;
int MAX_THREADS = 100;
int THREADSTACK = 65536;
struct thread_struct{
int arg1;
int arg2;
};
pthread_mutex_t mutex_;
static unsigned int thread_count = 0;
string exec(const char* cmd)
{
int DEBUG=0;
char buffer[5000];
string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe && DEBUG) throw runtime_error("popen() failed!");
try
{
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
}
catch(...)
{
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
void *thread_test(void *arguments)
{
pthread_mutex_lock(&mutex_);
thread_count++;
pthread_mutex_unlock(&mutex_);
// long tid;
// tid = (long)threadid;
struct thread_struct *args = (thread_struct*)arguments;
/*
printf("ARG1=%d\n",args->arg1);
printf("ARG2=%d\n",args->arg2);
*/
int thread_id = (int) args->arg1;
/*
int random_sleep;
random_sleep = rand() % 10 + 1;
printf ("RAND=[%d]\n", random_sleep);
sleep(random_sleep);
*/
int random_sleep;
random_sleep = rand() % 10 + 5;
// printf ("RAND=[%d]\n", random_sleep);
char command[100];
memset(command,0,sizeof(command));
sprintf(command,"sleep %d",random_sleep);
exec(command);
random_sleep = rand() % 100000 + 500000;
usleep(random_sleep);
// simulation of a work between 5 and 10 seconds
// sleep(random_sleep);
// printf("#%d -> sleep=%d total_threads=%u\n",thread_id,random_sleep,thread_count);
pthread_mutex_lock(&mutex_);
thread_count--;
pthread_mutex_unlock(&mutex_);
pthread_exit(NULL);
}
int main()
{
// pthread_t threads[NUM_THREADS];
int rc;
int i;
usleep(10000);
srand ((unsigned)time(NULL));
unsigned int thread_count_now = 0;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREADSTACK);
pthread_mutex_init(&mutex_, NULL);
for( i=0; i < NUM_THREADS; i++ )
{
create_thread:
pthread_mutex_lock(&mutex_);
thread_count_now = thread_count;
pthread_mutex_unlock(&mutex_);
// printf("thread_count in for = [%d]\n",thread_count_now);
if(thread_count_now < MAX_THREADS)
{
printf("CREATE thread [%d]\n",i);
struct thread_struct struct1;
struct1.arg1 = i;
struct1.arg2 = 999;
pthread_t temp_thread;
rc = pthread_create(&temp_thread, NULL, &thread_test, (void *)&struct1);
if (rc)
{
printf("Unable to create thread %d\n",rc);
sleep(1);
pthread_detach(temp_thread);
goto create_thread;
}
}
else
{
printf("Thread POOL full %d of %d\n",thread_count_now,MAX_THREADS);
sleep(1);
goto create_thread;
}
}
pthread_attr_destroy(&attrs);
pthread_mutex_destroy(&mutex_);
// pthread_attr_destroy(&attrs);
printf("Proccess completed!\n");
pthread_exit(NULL);
return 1;
}
After spawning 300 threads it begins to give
errors, return code from pthread_create() is 11, and after that keeps executing them one by one.
What im i doing wrong?
According to this website, error code 11 corresponds to EAGAIN which means according to this:
Insufficient resources to create another thread.
A system-imposed limit on the number of threads was encountered.
Hence to solve your problem either create less threads or wait for running ones to finish before creating new ones.
You can also change default thread stack size see pthread_attr_setstacksize

pthread_create() fails (invalid argument) every 60 threads on Xeon Phi

I have a piece of pthread code listed as the function "thread" here. It basically creates a number of threads (usually 240 on Xeon Phi and 16 on CPU) and then join them.
If I call this thread() only once, it works perfectly on both CPU and Xeon Phi. If I call it one more time, it still works fine on CPU but the pthread_create() will report "error 22" which should be "invalid argument" every 60 threads.
For example, thread 0, thread 60, thread 120 and so on of the 2nd run of thread() which are also the 241, 301, 361 and so on threads ever created in the process would fail (error 22). But thread 1~59, 61~119, 121~240, and so on work perfectly.
Note that this problem happens only on Xeon Phi.
I have checked the stack sizes, and the argument themselves, but I didn't find the reason for this. The arguments are correct.
void thread()
{
...
int i, rv;
cpu_set_t set;
arg_t args[nthreads];
pthread_t tid[nthreads];
pthread_attr_t attr;
pthread_barrier_t barrier;
rv = pthread_barrier_init(&barrier, NULL, nthreads);
if(rv != 0)
{
printf("Couldn't create the barrier\n");
exit(EXIT_FAILURE);
}
pthread_attr_init(&attr);
for(i = 0; i < nthreads; i++)
{
int cpu_idx = get_cpu_id(i,nthreads);
DEBUGMSG(1, "Assigning thread-%d to CPU-%d\n", i, cpu_idx);
CPU_ZERO(&set);
CPU_SET(cpu_idx, &set);
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &set);
args[i].tid = i;
args[i].ht = ht;
args[i].barrier = &barrier;
/* assing part of the relR for next thread */
args[i].relR.num_tuples = (i == (nthreads-1)) ? numR : numRthr;
args[i].relR.tuples = relR->tuples + numRthr * i;
numR -= numRthr;
/* assing part of the relS for next thread */
args[i].relS.num_tuples = (i == (nthreads-1)) ? numS : numSthr;
args[i].relS.tuples = relS->tuples + numSthr * i;
numS -= numSthr;
rv = pthread_create(&tid[i], &attr, npo_thread, (void*)&args[i]);
if (rv)
{
printf("ERROR; return code from pthread_create() is %d\n", rv);
printf ("%d %s\n", args[i].tid, strerror(rv));
//exit(-1);
}
}
for(i = 0; i < nthreads; i++)
{
pthread_join(tid[i], NULL);
/* sum up results */
result += args[i].num_results;
}
}
Here's a minimal example to reproduce your problem and show where your code most likely goes wrong:
#define _GNU_SOURCE
#include <pthread.h>
#include <err.h>
#include <stdio.h>
void *
foo(void *v)
{
printf("foo\n");
return NULL;
}
int
main(int argc, char **argv)
{
pthread_attr_t attr;
pthread_t thr;
cpu_set_t set;
void *v;
int e;
if (pthread_attr_init(&attr))
err(1, "pthread_attr_init");
CPU_ZERO(&set);
CPU_SET(255, &set);
if (pthread_attr_setaffinity_np(&attr, sizeof(set), &set))
err(1, "pthread_attr_setaffinity_np");
if ((e = pthread_create(&thr, &attr, foo, NULL)))
errx(1, "pthread_create: %d", e);
if (pthread_join(thr, &v))
err(1, "pthread_join");
return 0;
}
As I speculated in the comments to your question, pthread_attr_setaffinity_np doesn't check if the cpu set is sane. Instead that error gets caught in pthread_create. Since the cpu_get_id functions in your code on github are obviously broken, that's where I'd start looking for the problem.
Tested on Linux, but that's where pthread_attr_setaffinity_np comes from, so it's probably a safe assumption.

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);
}

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

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.