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;
Related
I would like to measure the execution time of some code. The code starts in the main() function and finishes in an event handler.
I have a C++11 code that looks like this:
#include <iostream>
#include <time.h>
...
volatile clock_t t;
void EventHandler()
{
// when this function called is the end of the part that I want to measure
t = clock() - t;
std::cout << "time in seconds: " << ((float)t)/CLOCKS_PER_SEC;
}
int main()
{
MyClass* instance = new MyClass(EventHandler); // this function starts a new std::thread
instance->start(...); // this function only passes some data to the thread working data, later the thread will call EventHandler()
t = clock();
return 0;
}
So it is guaranteed that the EventHandler() will be called only once, and only after an instance->start() call.
It is working, this code give me some output, but it is a horrible code, it uses global variable and different threads access global variable. However I can't change the used API (the constructor, the way the thread calls to EventHandler).
I would like to ask if a better solution exists.
Thank you.
Global variable is unavoidable, as long as MyClass expects a plain function and there's no way to pass some context pointer along with the function...
You could write the code in a slightly more tidy way, though:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
struct MyClass
{
typedef void (CallbackFunc)();
constexpr explicit MyClass(CallbackFunc* handler)
: m_handler(handler)
{
}
void Start()
{
std::thread(&MyClass::ThreadFunc, this).detach();
}
private:
void ThreadFunc()
{
std::this_thread::sleep_for(std::chrono::seconds(5));
m_handler();
}
CallbackFunc* m_handler;
};
std::promise<std::chrono::time_point<std::chrono::high_resolution_clock>> gEndTime;
void EventHandler()
{
gEndTime.set_value(std::chrono::high_resolution_clock::now());
}
int main()
{
MyClass task(EventHandler);
auto trigger = gEndTime.get_future();
auto startTime = std::chrono::high_resolution_clock::now();
task.Start();
trigger.wait();
std::chrono::duration<double> diff = trigger.get() - startTime;
std::cout << "Duration = " << diff.count() << " secs." << std::endl;
return 0;
}
clock() call will not filter out executions of different processes and threads run by scheduler in parallel with program event handler thread. There are alternative like times() and getrusage() which tells cpu time of process. Though it is not clearly mentioned about thread behaviour for these calls but if it is Linux, threads are treated as processes but it has to be investigated.
clock() is the wrong tool here, because it does not count the time actually required by the CPU to run your operation, for example, if the thread is not running at all, the time is still counted.
Instead you have to use platform-specific APIs, such as pthread_getcpuclockid for POSIX-compliant systems (Check if _POSIX_THREAD_CPUTIME is defined), that counts the actual time spent by a specific thread.
You can take a look at a benchmarking library I wrote for C++ that supports thread-aware measuring (see struct thread_clock implementation).
Or, you can use the code snippet from the man page:
/* Link with "-lrt" */
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void *
thread_start(void *arg)
{
printf("Subthread starting infinite loop\n");
for (;;)
continue;
}
static void
pclock(char *msg, clockid_t cid)
{
struct timespec ts;
printf("%s", msg);
if (clock_gettime(cid, &ts) == -1)
handle_error("clock_gettime");
printf("%4ld.%03ld\n", ts.tv_sec, ts.tv_nsec / 1000000);
}
int
main(int argc, char *argv[])
{
pthread_t thread;
clockid_t cid;
int j, s;
s = pthread_create(&thread, NULL, thread_start, NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
printf("Main thread sleeping\n");
sleep(1);
printf("Main thread consuming some CPU time...\n");
for (j = 0; j < 2000000; j++)
getppid();
pclock("Process total CPU time: ", CLOCK_PROCESS_CPUTIME_ID);
s = pthread_getcpuclockid(pthread_self(), &cid);
if (s != 0)
handle_error_en(s, "pthread_getcpuclockid");
pclock("Main thread CPU time: ", cid);
/* The preceding 4 lines of code could have been replaced by:
pclock("Main thread CPU time: ", CLOCK_THREAD_CPUTIME_ID); */
s = pthread_getcpuclockid(thread, &cid);
if (s != 0)
handle_error_en(s, "pthread_getcpuclockid");
pclock("Subthread CPU time: 1 ", cid);
exit(EXIT_SUCCESS); /* Terminates both threads */
}
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.
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.
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.
GLibC has a method semtimedop which allows you to perform an operation (a semaphore acquire in this case) which times out after a certain amount of time. Win32 also provides WaitForSingleObject which provides similar functionalty.
As far as I can see there is no equivalent on OSX or other Unices. Can you suggest either the equivalent for semtimedop or a workaround to terminate a semop after a certain amount of time cleanly.
You can break out of a semop() call (and most other blocking calls) by getting a signal, such as one caused by alarm().
untested example:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
volatile int alarm_triggered = 0;
void alarm_handler(int sig)
{
alarm_triggered = 1;
}
int main(int argc, char **argv)
{
int rc;
/* set up signal handler */
signal(SIGALRM, alarm_handler);
/* ... */
alarm(30); /* 30 second timeout */
rc = semop(...);
if (rc == -1 && errno == EINTR)
{
if (alarm_triggered)
{
/* timed out! */
}
}
alarm(0); /* disable alarm */
/* ... */
}