ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952
Rep:
how to properly use settimmer?
ok I am willing to learn how to make this work.
I can get my program to work on the cli. changing the image at a given time, now i just want to autotomize it to be able to set a time for it to call for another file to load off a (linked) list within the program.
I got the timer to cycle in some separate code using seconds, ( converting it to minutes after I get it to actually work), then I dropped it in my main code,
I've tried this about 5 different ways its getting late here so I'm posting my last attempt.
it gets checked here then called to set the time after setting the first image,
Code:
char *set_timer(void)
{
struct sigaction sa;
struct itimerval timer;
unsigned int whattime;
char *tempfile;
whattime = opts.cycletime;
printf("time %d\n",whattime);
// call to list to get next file
get_next_name_in_list();
tempfile = MH_FILE(filelist->data)->filename;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = whattime;
timer.it_interval.tv_usec = 0;
printf("time 2 %d\n",whattime);
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer ( ITIMER_REAL, &timer, NULL);
return(tempfile);
/* Do busy work. */
while ( opts.cycletime > 0);
return(tempfile);
}
It sends an image filename from the return and it loads and displays in the background, I just cannot at this time figure out how to get it to do it again, after the first call.
You are properly using setitimer(), the comments do not match the timer values, you are using 1 second for the first timeout value and then whatever is in the value of 'whattime' for the repeat timeout values.
You don't show your timer handler.
I have code which does work, which uses SIGALRM, which may or may not be the same numerical value for the SIG you are using. Or multiple signals may also occur at timeout.
Those are really the technical differences I notice in what you're using. Not sure if they're enough where things won't work, just that the timeouts are not 250 mS as your comment states. They can't be when you're using the tv_sec portion of the structure. Use the tv_usec and if the value is 250,000 then it will be 250 mSec.
Next, my timer_handler() increments a counter. My main loop checks that counter against a value and once it overflows, it will do the desired action, and it will reset the counter. The timer_handler() runs forever, always just incrementing the counter.
Additional thought is that say my desired time is 1/2 of a second, or 500 mSec. My timer_handler() function, run by my itimer, actually runs at maybe 20 mSec. The timer_handler() increments a counter each time. So my main loop checks that count to see if it exceeds a value of 25. Because 25 times 20 mSec works out to be 500 mSec. That's how I do it versus allowing the itimer to give me a single event.
It might be more helpful for you to not edit your posts. Because you asked an initial question, you've worked through it, and then you edit your post and no one can tell if your first question is still a question.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
You are properly using setitimer(), the comments do not match the timer values, you are using 1 second for the first timeout value and then whatever is in the value of 'whattime' for the repeat timeout values.
You don't show your timer handler.
I have code which does work, which uses SIGALRM, which may or may not be the same numerical value for the SIG you are using. Or multiple signals may also occur at timeout.
Those are really the technical differences I notice in what you're using. Not sure if they're enough where things won't work, just that the timeouts are not 250 mS as your comment states. They can't be when you're using the tv_sec portion of the structure. Use the tv_usec and if the value is 250,000 then it will be 250 mSec.
Next, my timer_handler() increments a counter. My main loop checks that counter against a value and once it overflows, it will do the desired action, and it will reset the counter. The timer_handler() runs forever, always just incrementing the counter.
Additional thought is that say my desired time is 1/2 of a second, or 500 mSec. My timer_handler() function, run by my itimer, actually runs at maybe 20 mSec. The timer_handler() increments a counter each time. So my main loop checks that count to see if it exceeds a value of 25. Because 25 times 20 mSec works out to be 500 mSec. That's how I do it versus allowing the itimer to give me a single event.
It might be more helpful for you to not edit your posts. Because you asked an initial question, you've worked through it, and then you edit your post and no one can tell if your first question is still a question.
Good morning, because that is what time it is here, first things first LQ, and replies,
and yeah I was having a hard time figuring out how this thing worked, because the handler is not called in that body of code, at least I could not see it using the function call timer_handler(int varName); and probably still am because I have not yet played with it as of yet.
As this is off the net example, It looked like it will suit my purposes,so why write another one?.
When running it in a separate main where the body of the code was in main, and the time handler as posted in here - I put that in too, and not seeing it actually calling the function within the code confused me, but I added it to mine none the less in the same file that the set-timer is in then made a different function to be call within it, thinking maybe that is how this thing is working, still got nothing. the seconds I was using because that is what they are there for to, to use seconds instead of milliseconds - it doesn't have to be that precise.
So i was just fiddling with it to see what the times do to get it down to seconds instead. the first one is to set it to wait time, and the second one is to set it to how long before repeating, that was my understanding of it. so 1 sec wait time, then whatever the user put it in the command line to set it to minutes, that has not been converted yet, but converting seconds is easier then milliseconds less zeros to count. so I was just using seconds for trial,
sorry I was in a bit of a hurry posting this,
the setting are just to see if i can get it to work, one second wait times any faster and imlib will not have time to load and display an image.
Code:
unsigned int whattime; <- next time place holder
whattime = opts.cycletime; <-- how it is passed to it
// Configure the timer to expire after 1 second
timer.it_value.tv_sec = 1; <-- one second to start
timer.it_value.tv_usec = 0; <-- not being used so zero.
// then again every X=seconds after that.
timer.it_interval.tv_sec = whattime; <- set here by whatever the user puts in the command line.
testing is set to use just seconds
timer.it_interval.tv_usec = 0; <- not used because seconds is short / fast enough -
printf("time 2 %d\n",whattime);
the rest of that code is in the first post. I tried timer.it_interval.tv_usec with it being commented out and only using seconds but it would not work at all in the other main I was testing it in. So I put them back and set them to zero and it started working again.
still needs to be set to minutes (whattime * 60) but that can wait until I get it to work first.
so maybe it just has to be where I am putting the functions
timer_handler
set_timer
are in the same c file,
cycle_images()
is in the file where the list is called so it will not need a return value, though I may have to go back and double check that to be sure.
after I post this I am going to go back and chew on what you posed some more.
MOD:
I know it has to be some little simple mistake, as I call cycle_images() from main too, just to see if it pulls a filename from that function to be passed to the loadimage function to set the image to the desktop, and it gets a filename,
Code:
in main cycle images <-- printf just before the cycle_images function call
load image cycle time 3
file-> /media/data/test/128/Heidy-Pino-001-0750.png <-- out put from that function.
it still does not seem to work, because no images are changing on the desktop. or more output from printf in the terminal indicating it is being called again.
Good morning, because that is what time it is here, first things first LQ, and replies
It's morning here too, just a tad later
Quote:
Originally Posted by BW-userx
and yeah I was having a hard time figuring out how this thing worked, because the handler is not called in that body of code, at least I could not see it using the function call timer_handler(int varName); and probably still am because I have not yet played with it as of yet.
timer_handler() is called when the itimer expires, because this is part of the sa structure when you defined the timer.
Quote:
Originally Posted by BW-userx
As this is off the net example, It looked like it will suit my purposes,so why write another one?
Totally agree, however one always should learn from the Internet examples and understand where you need to alter it for your needs. You're getting there, don't worry.
When running it in a separate main where the body of the code was in main, and the time handler as posted in here - I put that in too, and not seeing it actually calling the function within the code confused me, but I added it to mine none the less in the same file that the set-timer is in then made a different function to be call within it, thinking maybe that is how this thing is working, still got nothing. the seconds I was using because that is what they are there for to, to use seconds instead of milliseconds - it doesn't have to be that precise.
As far as the rest of what you've discussed, and your concern about running the updates to the UI, how about you verify that the timing is correct, that the timeouts do occur and getting that part correct, before you worry about whether or not it is calling your update function.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
It's morning here too, just a tad later timer_handler() is called when the itimer expires, because this is part of the sa structure when you defined the timer.Totally agree, however one always should learn from the Internet examples and understand where you need to alter it for your needs. You're getting there, don't worry.
When running it in a separate main where the body of the code was in main, and the time handler as posted in here - I put that in too, and not seeing it actually calling the function within the code confused me, but I added it to mine none the less in the same file that the set-timer is in then made a different function to be call within it, thinking maybe that is how this thing is working, still got nothing. the seconds I was using because that is what they are there for to, to use seconds instead of milliseconds - it doesn't have to be that precise.
As far as the rest of what you've discussed, and your concern about running the updates to the UI, how about you verify that the timing is correct, that the timeouts do occur and getting that part correct, before you worry about whether or not it is calling your update function.
this is what I just did using that example. I put it in a different function then called it in main.
Code:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer expired %d times\n", ++count);
}
void timer_setting(int elapstime){
struct sigaction sa;
struct itimerval timer;
/* Install timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 250 msec... */
timer.it_value.tv_sec = 1; <-- set to start after 1 sec
timer.it_value.tv_usec = 0;
/* ... and every 250 msec after that. */
timer.it_interval.tv_sec = elapstime; <--- TIME (seconds) gets set here from prams
timer.it_interval.tv_usec = 0;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_VIRTUAL, &timer, NULL);
/* Do busy work. */
while (1);
}
int main ()
{
timer_setting(3);
return 0;
}
which worked, then when I changed ITIMER_VIRTUAL to ITIMER_REAL it only ran one time then stopped, though using ITIMER_VIRTUAL definitely is not actually one second because of its nature, it is not real time, it for whatever its reasons kept working, the results:
Code:
//with ITIMER_REAL
userx%slackwhere ⚡ bin ⚡> gcc settimer.c -o timer2
userx%slackwhere ⚡ bin ⚡> ./timer2
Alarm clock
// with ITIMER_VIRTUAL
userx%slackwhere ⚡ bin ⚡> gcc settimer.c -o timer2
userx%slackwhere ⚡ bin ⚡> ./timer2
timer expired 1 times
timer expired 2 times
timer expired 3 times
timer expired 4 times
SO I am going to try changing it to ITIMER_VIRTUAL in my main code and see if that does the trick.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,952
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
I use ITIMER_REAL and it works fine for me. However you go with what works and try to explain it by reading the man pages.
And actually here is the difference, which is something I already mentioned (courtesy setitimer(2)):My recommendation is always that people review the manual pages properly when they are using new functions.
This is the type of signal handler functions. Signal handlers take one integer argument specifying the signal number,
and have return type void. So, you should define handler functions like this:
void handler (int signum) { … } <-- I guess do something within that body between the brackets.
but when calling that handler function in another file, I ran it in the test main file.
but there is no declared int for signum to work, so I am guessing it is just out there in la la linux land OS somewhere to get magically pulled into but not associated with anything.
Code:
// To load normally - orginal Image sizes
int load_image(ImageMode mode, int alpha, int use_filelist)
{
int signum2;
int left = 0, top = 0, x = 0, y = 0, imgW = 0, imgH = 0;
if (opts.cycletime > 0)
{
// get_next_name_in_list();
//filename = MH_FILE(filelist->data)->filename;
//filename = set_timer();
set_timer(opts.cycletime);
printf("set_time called in load image\n");
get_next_name_in_list();
filename = MH_FILE(filelist->data)->filename;
printf("cycle time Load image -> %s\n",filename);
timer_handler (signum2); <-- figuring out what variable name to pass in there is got me stuck because I keep getting errors.
printf("IMGLOAD TIMER HANDLER\n");
}
else
{
get_next_name_in_list();
filename = MH_FILE(filelist->data)->filename;
}
.....
}
because the way I see it when you take everything out of main where it is globally set, one still needs to call the timer_handler function like all of the other functions in order for them to be utilized within the code.
anyways I found a different way and it worked but it does not release the program in the terminal
Context & Trivial example, via Inter-Dimensional Portal
From "Linux La-La Land" :-)
First, the Context, signal numbers and the types of events to which they correspond. On various Linux-en, Cygwin, and various other environments, it is possible to do this from the command line:
this is a command prompt > setitimer_use 2
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
Got Sig, Sig was 'Alarm clock'.
^C
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.