struct itimerspec as timer_create's parameter invalid argument - c

I was trying POSIX timers togheter with POSIX signals handling.
When I try to excecute the code you can find downhere, I get:
Errore timer_settime: Invalid argument
On GAPIL book, that is based upon Advanced Linux Programming and Unix network programming, I read that this can happen when inside new_value.value you specified a negative time value or a number of nanoseconds higher than 999999999.
But I think that parameters I have used are okay...
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/fcntl.h>
#include <sys/wait.h>
#include <stdbool.h>
void termination_handler(int signum)
{
printf("Timer scaduto\n");
}
int main()
{
timer_t timer1;
struct sigevent sigeventStruct;
sigeventStruct.sigev_notify = SIGEV_SIGNAL;
sigeventStruct.sigev_signo = 10;
if(timer_create(_POSIX_MONOTONIC_CLOCK, &sigeventStruct, &timer1) == -1)
{
printf( "Errore timer_create: %s\n", strerror( errno ) );
}
printf("timer_create eseguito\n");
struct itimerspec tempoIniziale;
tempoIniziale.it_value.tv_nsec = 0;
struct itimerspec tempoFinale;
tempoFinale.it_value.tv_nsec = 10000000;
if(timer_settime(timer1, 0, &tempoIniziale, &tempoFinale) == -1)
{
printf( "Errore timer_settime: %s\n", strerror( errno ) );
}
struct sigaction newSigAzione, oldSigAzione;
newSigAzione.sa_handler = termination_handler;
//oldSigAzione.sa_handler = termination_handler;
sigemptyset (&newSigAzione.sa_mask);
newSigAzione.sa_flags = 0;
sigaction (SIGEV_SIGNAL, NULL, &oldSigAzione);
if(oldSigAzione.sa_handler != SIG_IGN)
{
//sigaction (SIGEV_SIGNAL, newSigAzione, NULL);
}
/*sigaction (SIGINT, NULL, &oldSigAzione);
if (oldSigAzione.sa_handler != SIG_IGN)
sigaction (SIGINT, &newSigAzione, NULL);
sigaction (SIGHUP, NULL, &oldSigAzione);
if (oldSigAzione.sa_handler != SIG_IGN)
sigaction (SIGHUP, &newSigAzione, NULL);
sigaction (SIGTERM, NULL, &oldSigAzione);
if (oldSigAzione.sa_handler != SIG_IGN)
sigaction (SIGTERM, &newSigAzione, NULL);*/
/*sigaction (SIGTERM, &newSigAzione, NULL);*/
return 0;
}

_POSIX_MONOTONIC_CLOCK is a feature test macro that tells you whether monotonic clocks are available on the system.
The available clock ids you can pass to timer_create() on Linux are:
CLOCK_REALTIME
System-wide realtime clock. Setting this clock requires appropriate privileges.
CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time since some unspecified starting point.
CLOCK_PROCESS_CPUTIME_ID
High-resolution per-process timer from the CPU.
CLOCK_THREAD_CPUTIME_ID
Thread-specific CPU-time clock.
You must also initialize all the members in struct sigevent and struct itimerspec.
E.g. you don't set .tv_sec in the structitimer_spec, only .tv_nsec , which results in garbage values in those members.
...
memset(&sigeventStruct, 0, sizeof sigeventStruct);
...
and
struct itimerspec tempoFinale;
memset(&tempoFinale, 0, sizeof tempoFinale);
tempoFinale.it_value.tv_nsec = 10000000;

Related

Printing the default thread's priority

I'd like to write a code which prints the default thread's priority, but I don't know if this is possible. So far I created a thread with default attributes, but I didn't find any statement which allows me to store and print its default priority.
// main.c
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include "task.h"
int main()
{
pthread_attr_t attr;
struct sched_param prio;
pthread_t tid;
int create = 1;
// default attributes
pthread_attr_init(&attr);
create = pthread_create(&tid, &attr, task, NULL);
if (create != 0) exit(EXIT_FAILURE);
pthread_join(tid, NULL);
return(0);
}
// task.h
#ifndef TASK_H
#define TASK_H
void *task();
#endif
// task.c
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "task.h"
void *task()
{
printf("I am a simple thread.\n");
pthread_exit(NULL);
}
I didn't find any statement which allows me to store and print its default priority.
It's pthread_attr_getschedparam and sched_param has scheduling priority (at least).
struct sched_param prio;
pthread_attr_getschedparam(&attr, &prio);
printf("sched_priority = %d\n", prio.sched_priority);

How to get every integer second in a c program

I am wondering if there is a way to get every integer second in a c program. I tried to use 'gettimeofday' function to get the current time and then if the current fractional part of second falls into a region (say larger than 0.9 and smaller than 0.1), I rounded the current time into an integer. However, when I run the program, occasionally, there were a few seconds missed. Does anyone have a better solution?
Thanks
I would suggest to use the alarm signal:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
void timer_handler (int signum)
{
struct timeval tval;
gettimeofday(&tval, NULL);
printf("Seconds: %ld\n",tval.tv_sec);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_VIRTUAL, &timer, NULL);
while (1);
}
At my Mac (OS X 10.11.5) I get:
./alarm
Seconds: 1468937712
Seconds: 1468937713
Seconds: 1468937714
Seconds: 1468937715
Seconds: 1468937716
Seconds: 1468937717
Seconds: 1468937718
Seconds: 1468937719
Seconds: 1468937720
EDIT
The code above uses the virtual timer, that only ticks als long the thread is running (and thus relies on the busy loop the introduce the high load). Using the real timer allows for reduction of the load:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
void timer_handler (int signum)
{
struct timeval tval;
printf("Foo");
gettimeofday(&tval, NULL);
printf("Seconds: %ld\n",tval.tv_sec);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
sa.sa_mask=0;
sa.sa_flags=0;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM, &sa, NULL);
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
while (1){
pthread_yield_np();
}
}
This approach runs basically the timer handler only. Thus the OS shouldn't care to much about load. However, be aware that hard real-time guarantees one get by OS's real-time features only (if there are any).

Can we reset sigsetjmp to return "0" again (Reset sigsetjmp)?

I have written a segmentation fault handler, using sigsetjmp and siglongjmp. Once it goes to the signal handler, i invoke siglongjmp so that the faulty instruction is skipped.
Problem is, i again want to cause SIGSEGV and go to the same handler, but now sigsetjmp will return 1.
How to reset sigsetjmp?
Here is my code:
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
sigjmp_buf env, env1;
void SIGSEGV_handler(int signal)
{
printf("Segmentation fault caught\n");
siglongjmp(env, 1);
}
int main()
{
void * allocation;
size_t size;
static int devZerofd = -1;
struct sigaction sa, sa1;
sa.sa_handler=(void*)SIGSEGV_handler;
sigaction(SIGSEGV, &sa, NULL);
if ( devZerofd == -1 ) {
devZerofd = open("/dev/zero", O_RDWR);
if ( devZerofd < 0 )
perror("open() on /dev/zero failed");
}
allocation = (caddr_t) mmap(0, 5000, PROT_READ|PROT_NONE, MAP_PRIVATE, devZerofd, 0);
if ( allocation == (caddr_t)-1 )
fprintf(stderr, "mmap() failed ");
if ( mprotect((caddr_t)allocation, 5000, PROT_NONE) < 0 )
fprintf(stderr, "mprotect failed");
else
printf("mprotect done: memory allocated at address %u\n",allocation);
if(sigsetjmp(env, 1)==0) {
printf("Causing SIGSEGV: 1\n");
strcpy(allocation,"Hello, how are you");
}
/****** This can't be done again as sigsetjmp won't return 0*****/
/*
if(sigsetjmp(env, 1)==0) {
printf("Causing SIGSEGV: 1\n");
strcpy(allocation,"Hello, how are you");
}
*/
}
You have misunderstood how [sig]setjmp works. If you uncomment the code that you think won't work, compile it, and run it, you will see that it does in fact work.
setjmp cannot be made to return zero by calling longjmp. If you call setjmp itself a second time, even with the same jmp_buf (as you do here), it will return zero a second time.
You have a bug, by the way: you didn't set up your sigaction parameter structure correctly. You should have done this:
struct sigaction sa;
sa.sa_handler = SIGSEGV_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, 0);
The use of mmap is a little infelicitous, but not actually buggy. You don't need /dev/zero on most current platforms, you can just use MAP_ANON (some platforms spell it MAP_ANONYMOUS) and a -1 fd argument. And you should be using getpagesize and then asking for a whole number of pages.

Virtual time expired

I have the following code, which throws the error
Virtual time expired.
Shouldn't the program run in an infinite loop?
#define KTHREAD_VTALRM_SEC 0
#define KTHREAD_VTALRM_USEC 100000
#include <stdio.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sched.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
int main()
{
struct itimerval timeslice;
timeslice.it_interval.tv_sec = KTHREAD_VTALRM_SEC;
timeslice.it_interval.tv_usec = KTHREAD_VTALRM_USEC;
timeslice.it_value.tv_sec = KTHREAD_VTALRM_SEC;
timeslice.it_value.tv_usec = KTHREAD_VTALRM_USEC;
setitimer(ITIMER_VIRTUAL,&timeslice,NULL);
while(1)
{
;
}
}
When the timer expires it will deliver a SIGVTALRM signal, which you are not handling.
See the man pages for setitimer() and signal().
You did not set a signal handler.
The default handler for VTALRM signal is "exit" (ref: http://manpages.ubuntu.com/manpages//precise/en/man1/kill.1.html.)
So if you want to replace the default behavior with yours, you have to define a new signal handler and register it:
void vtHandler(int sig)
{
// Do something here
}
int main()
{
// Register timer handler
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = timer_handler;
if (sigaction(SIGVTALRM, &sa, NULL) == -1)
//error handle
;
}
PS: If you utilize signal method, sure that it is well implemented on your system (ref: http://manpages.ubuntu.com/manpages//precise/en/man2/signal.2.html)

multiple timer to one process (without linking to rt)

is there any way to register multiple timer to a single process? I have tried following code, yet without success. (Use "gcc -lrt" to compile it...). Program output nothing, which should atleast print "test". Is it possibly due to the dependence to linking to rt?
#define TT_SIGUSR1 (SIGRTMAX)
#define TT_SIGUSR2 (SIGRTMAX - 1)
#define TIME_INTERVAL_1 1
#define TIME_INTERVAL_2 2
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sched.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <assert.h>
timer_t create_timer(int signo) {
timer_t timerid;
struct sigevent se;
se.sigev_signo = signo;
if (timer_create(CLOCK_REALTIME, &se, &timerid) == -1) {
fprintf(stderr, "Failed to create timer\n");
exit(-1);
}
return timerid;
}
void set_timer(timer_t timerid, int seconds) {
struct itimerspec timervals;
timervals.it_value.tv_sec = seconds;
timervals.it_value.tv_nsec = 0;
timervals.it_interval.tv_sec = seconds;
timervals.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &timervals, NULL) == -1) {
fprintf(stderr, "Failed to start timer\n");
exit(-1);
}
return;
}
void install_sighandler2(int signo, void(*handler)(int)) {
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
//register the Signal Handler
sigact.sa_sigaction = handler;
// Set up sigaction to catch signal first timer
if (sigaction(signo, &sigact, NULL) == -1)
{
printf("sigaction failed");
return -1;
}
}
void install_sighandler(int signo, void(*handler)(int)) {
sigset_t set;
struct sigaction act;
/* Setup the handler */
act.sa_handler = handler;
act.sa_flags = SA_RESTART;
sigaction(signo, &act, 0);
/* Unblock the signal */
sigemptyset(&set);
sigaddset(&set, signo);
sigprocmask(SIG_UNBLOCK, &set, NULL);
return;
}
void signal_handler(int signo) {
printf("receiving sig %d", signo);
}
int main()
{
printf("test");
timer_t timer1 = create_timer(TT_SIGUSR1);
timer_t timer2 = create_timer(TT_SIGUSR2);
set_timer(timer1, TIME_INTERVAL_1);
set_timer(timer2, TIME_INTERVAL_2);
install_sighandler2(TT_SIGUSR1, signal_handler);
install_sighandler(TT_SIGUSR2, signal_handler);
while (1)
;
return 0;
}
missing in create_timer: se.sigev_notify=SIGEV_SIGNAL;
two install_sighandler methods. Install_sighandler2 has a compler warning about mismatching pointer types.
while (1) will hog your processor, sleep.
#define TT_SIGUSR1 (SIGUSR1)
#define TT_SIGUSR2 (SIGUSR2)
#define TIME_INTERVAL_1 1
#define TIME_INTERVAL_2 2
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sched.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
timer_t create_timer(int signo) {
timer_t timerid;
struct sigevent se;
se.sigev_notify=SIGEV_SIGNAL;
se.sigev_signo = signo;
if (timer_create(CLOCK_REALTIME, &se, &timerid) == -1) {
perror("Failed to create timer");
exit(-1);
}
return timerid;
}
void set_timer(timer_t timerid, int seconds) {
struct itimerspec timervals;
timervals.it_value.tv_sec = seconds;
timervals.it_value.tv_nsec = 0;
timervals.it_interval.tv_sec = seconds;
timervals.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &timervals, NULL) == -1) {
perror("Failed to start timer");
exit(-1);
}
return;
}
void install_sighandler(int signo, void(*handler)(int)) {
sigset_t set;
struct sigaction act;
/* Setup the handler */
act.sa_handler = handler;
act.sa_flags = SA_RESTART;
sigaction(signo, &act, 0);
/* Unblock the signal */
sigemptyset(&set);
sigaddset(&set, signo);
sigprocmask(SIG_UNBLOCK, &set, NULL);
return;
}
void signal_handler(int signo) {
printf("receiving sig %d\n", signo);
}
int main()
{
printf("test\n");
timer_t timer1 = create_timer(TT_SIGUSR1);
timer_t timer2 = create_timer(TT_SIGUSR2);
install_sighandler(TT_SIGUSR1, signal_handler);
install_sighandler(TT_SIGUSR2, signal_handler);
set_timer(timer1, TIME_INTERVAL_1);
set_timer(timer2, TIME_INTERVAL_2);
while (1) sleep(1);
return 0;
}

Resources