Given the following code, the expectation is for there to be a one-second sleep each time select() is called. However, the sleep only occurs on the first call and all subsequent calls result in no delay:
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
for (;;)
{
/* Sleep for one second */
int result=select(0, NULL, NULL, NULL, &tv);
printf("select returned: %d\n",result);
}
}
Why do all calls to select() except the first return immediately?
Compiler: gcc 4.9.2
OS: Centos 7 (Linux)
Kernel info: 3.10.0-327.36.3.el7.x86_64
From the man page:
On Linux, select() modifies timeout to reflect the amount of time not
slept
So, set tv [in the loop] before calling select
As stated in the manpage
On Linux, select() modifies timeout to reflect the amount of time not
slept; most other implementations do not do this. (POSIX.1 permits
either behavior.) This causes problems both when Linux code which
reads timeout is ported to other operating systems, and when code is
ported to Linux that reuses a struct timeval for multiple select()s
in a loop without reinitializing it. Consider timeout to be unde‐
fined after select() returns.
As the first run ended by timeout, the tv value is reset to 0 seconds. Solution: reinitialize tv on every run.
Related
I need to use some timers in my code. I've got something like this:
struct sigevent ec;
ec.sigev_notify = SIGEV_THREAD;
ec.sigev_value.sival_ptr = &c_timer;
ec.sigev_notify_function = c_thread;
ec.sigev_notify_attributes = NULL;
secs = floor(c);
nsecs = (long long) SECOND * (c - secs);
printf("%ds\t%lldns\n\n",secs,nsecs);
it1c.it_value.tv_sec = secs;
it1c.it_value.tv_nsec = nsecs;
it1c.it_interval.tv_sec = 0;
it1c.it_interval.tv_nsec = 0;
timer_create(CLOCK_PROCESS_CPUTIME_ID, &ec, &c_timer);
timer_settime(c_timer, 0, &it1c, NULL);
Where c_thread is some simple function which is setting new timer, SECOND is:
#define SECOND 1000000000
c is something like 2.25
And my problem is that this timer doesn't call c_thread when it should. When i change CLOCK_PROCESS_CPUTIME_ID to CLOCK_REALTIME everything is ok, and it is called, but when I am using first one nothing happens. I am also checking CLOCK_PROCESS_CPUTIME_ID using other CLOCK_REALTIME timer with clock_gettime function and values of clock reach my it_value.
Any ideas what could be wrong?
And my second question: Is there any way to pass some arguments to function called as thread using timers?
#annamataris problem was not related to spinlock and nanosleep stuff. There is reason to use only CLOCK_REALTIME because.
The POSIX timers system calls first appeared in Linux 2.6. Prior to
this, glibc provided an incomplete user-space implementation
(CLOCK_REALTIME timers only) using POSIX threads, and in glibc
versions before 2.17, the implementation falls back to this technique
on systems running pre-2.6 Linux kernels.
Read man timer_create for more info.
I expect that gettimeofday() will call a system call to do the work of actually getting the time. However, running the following program
#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
struct timeval tv;
printf("Before gettimeofday() %ld!\n", tv.tv_sec);
int rc = gettimeofday(&tv, NULL);
printf("After gettimeofday() %ld\n", tv.tv_sec);
if (rc == -1) {
printf("Error: gettimeofday() failed\n");
exit(1);
}
printf("Exiting ! %ld\n", tv.tv_sec);
return 0;
}
under dtruss -d returns a long list of system calls, the last of which are:
RELATIVE SYSCALL(args) = return
... lots of syscalls with earlier timestamps ...
3866 fstat64(0x1, 0x7FFF56ABC8D8, 0x11) = 0 0
3868 ioctl(0x1, 0x4004667A, 0x7FFF56ABC91C) = 0 0
3882 write_nocancel(0x1, "Before gettimeofday() 0!\n\0", 0x19) = 25 0
3886 write_nocancel(0x1, "After gettimeofday() 1480913810\n\0", 0x20) = 32 0
3887 write_nocancel(0x1, "Exiting ! 1480913810\n\0", 0x15) = 21 0
It looks like gettimeofday() isn't using a syscall, but this seems wrong-surely the kernel takes responsibility of the system clocks? Is dtruss missing something? Am I reading the output incorrectly?
As TheDarkKnight pointed out, there is a gettimeofday system call. However, the userspace gettimeofday function often does not call the corresponding system call, but rather __commpage_gettimeofday, which tries to read the time from a special part of the process' address space called the commpage. Only if this call fails does the gettimeofday system call get used as a fallback. This reduces the cost of most calls to gettimeofday from that of an ordinary system call to just a memory read.
The book Mac OSX Internals: A Systems Approach describes the commpage. Briefly, it is a special area of kernel memory that is mapped into the last eight pages of the address space of every process. Among other things, it contains time values that are "updated asynchronously from the kernel and read atomically from user space, leading to occasional failures in reading".
To see how often the gettimeofday() system call is called by the userspace function, I wrote a test program that called gettimeofday() 100 million times in a tight loop:
#include <sys/time.h>
int main(int argc, char const *argv[])
{
const int NUM_TRIALS = 100000000;
struct timeval tv;
for (int i = 0; i < NUM_TRIALS; i++) {
gettimeofday(&tv, NULL);
}
return 0;
}
Running this under dtruss -d on my machine showed that this triggered between 10-20 calls to the gettimeofday() system calls (0.00001%-0.00002% of all the userspace calls).
For those interested, the relevant lines in the source code for the userspace gettimeofday() function (for macOS 10.11 - El Capitan) are
if (__commpage_gettimeofday(tp)) { /* first try commpage */
if (__gettimeofday(tp, NULL) < 0) { /* if it fails, use syscall */
return (-1);
}
}
The function __commpage_gettimeofday combines the timestamp read from the commpage and a reading of the time stamp counter register to calculate the time since epoch in seconds and microseconds. (The rdstc instruction is inside _mach_absolute_time.)
The use of dtrace instead of dtruss will clear your doubt.
gettimeofday() is itself a system call. You can see this system call getting called if you run dtrace script.
You can use following dtrace script
"dtrace1.d"
syscall:::entry
/ execname == "foo" /
{
}
(foo is the name of your executable)
to run above dtrace use: dtrace -s dtrace1.d
and then execute your program to see all system call used by your program
I am new to sockets programming and I'm trying to thoroughly understand how it works, but for now I'm really stuck on select().
The problem is that in my code, after select detects activity and the fd stays set, it seems that on next iterations FD_ISSET will return true automatically, like it would ignore the select function. The problem seems to be identical to this one, but I did all that I found there and to no avail: http://compgroups.net/comp.unix.programmer/how-does-fd_isset-return-0-after-returne/55058
I made sure to reinitialize the timeval variable after select() since I'm on Linux and I understood this function behaves differently on different OSes, I also reinitialized the fd set with FD_ZERO and FD_SET before select.
What am I doing wrong? Here is the code:
#include <stdio.h>
#include <strings.h>
#include <sys/select.h>
#include <sys/time.h>
int main () {
struct timeval tv;
tv.tv_sec = 5; // 5 seconds timeout
tv.tv_usec = 0;
fd_set afds, rfds;
FD_ZERO(&afds);
FD_SET(0, &afds);
while (1) {
rfds = afds;
select(1, &rfds, NULL, NULL, &tv);
// linux, reinitialize tv?
tv.tv_sec = 5;
tv.tv_usec = 0;
// so at this point after select runs the first time and detects STDIN activity
// it will enter an infinite loop printing "fd 0 is set" (why?)
if (FD_ISSET(0, &rfds)) {
printf("fd 0 is set\n");
FD_CLR(0, &rfds);
} else {
printf("fd 0 is NOT set\n");
}
}
}
Question edit since I'm a new user and can't answer this:
The fact is I initialize rfds before select when it is assigned the value of afds, which in turn is always set with FD_ZERO(&afds); FD_SET(0, &afds); This still doesn't work for me.
Here's what I understand:
I add stdin file descriptor to afds
Enter while infinite loop, rfds = afds (rfds will always be = afds at the start of the loop)
Also, at this time, FD_ISSET(0, &rfds) will always be != 0
select has a timeout of 5 seconds, so at this time if I don't type anything before the 5 seconds pass, it exits, UNSETTING FD_ISSET(0, &rfds) - is that correct? so select will actually unset the fd 0 if nothing is typed. This seems to work OK
The problem arrives when I type something before the timeout. At this point, FD_ISSET(0, &rfds) returns != 0, it prints fd 0 is set, and then each loop fd will be set
Ok, is this accurate, did I get it right? So practically select doesn't wait for the time to pass because it actually detects that the fd is ready and exits, setting the fd != 0 ?
Which would beg for a further question: if I need the server to send automatically messages to several clients every once in a while (independently of what it reads from clients), would it be possible to do it with select and gettimeofday by adapting the code above?
Thanks for the help.
select() is level-triggered, not edge-triggered. When you pass it a set of file descriptors, it will come back telling you which ones are readable/writable/exceptional at the moment, not just the ones that have changed state recently.
In this case, fhe FD is being marked as readable every time you call select() because you're not doing anything to make it not readable (like draining the available input) when it shows up.
The values stored in your fd_set do remain after select() fires. In an application it is possible for select() to monitor many sockets. Automatically cleaning the fd_set would mean you could never detect that multiple sockets need servicing.
You need to do your FD_ZERO() and FD_SET() inside the infinite loop so that on each pass the fd_set is initialized cleanly before select() is called.
I have to call one method in seperate thread (i am using posix thread)which updates some value after every 5 second for which have written below code.
void *threadEntry(void *)
{
while(1)
{
updateValue();//to update some values
usleep(5000000);//pause for 5 second
}
}
pthread_t thread1;
pthread_create(&thread1,NULL,threadEntry,NULL);
But this thread gets segmentation fault after 4-5 minutes .What can be reason?Is there any other way to pause the posix thread.(i am using linux)
On POSIX systems (which linux is) nanosleep is the right thing for such a sleep:
int nanosleep(const struct timespec *req, struct timespec *rem);
where req is your request an rem is the time remaining to sleep if your thread was interrupted prematurely.
The right thing to do is to use nanosleep, because usleep and sleep might mess with SIGALARM, while nanosleep was specifically designed with threads in mind :
struct timespec mytimeout = {
.tv_sec = 5,
.tv_usec = 0,
};
struct timespec remaining;
nanosleep(&mytimeout, &remaining);
My original answer was to use a select trick, but let's stop promoting bad code
Back to the root of the problem, how do you know your segmentation fault come from the sleeping code ?
Did you get a core dump you could backtrace ?
I'm using select() on a Linux/ARM platform to see if a udp socket has received a packet. I'd like to know how much time was remaining in the select call if it returns before the timeout (having detected a packet).
Something along the lines of:
int wait_fd(int fd, int msec)
{
struct timeval tv;
fd_set rws;
tv.tv_sec = msec / 1000ul;
tv.tv_usec = (msec % 1000ul) * 1000ul;
FD_ZERO( & rws);
FD_SET(fd, & rws);
(void)select(fd + 1, & rws, NULL, NULL, & tv);
if (FD_ISSET(fd, &rws)) { /* There is data */
msec = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
return(msec?msec:1);
} else { /* There is no data */
return(0);
}
}
The safest thing is to ignore the ambiguous definition of select() and time it yourself.
Just get the time before and after the select and subtract that from the interval you wanted.
If I recall correctly, the select() function treats the timeout and an I/O parameter and when select returns the time remaining is returned in the timeout variable.
Otherwise, you will have to record the current time before calling, and again after and obtain the difference between the two.
From "man select" on OSX:
Timeout is not changed by select(), and may be reused on subsequent calls, however it
is good style to re-ini-tialize it before each invocation of select().
You'll need to call gettimeofday before calling select, and then gettimeofday on exit.
[Edit] It seems that linux is slightly different:
(ii) The select function may update the timeout parameter to indicate
how much time was left. The pselect function does not change
this parameter.
On Linux, the function select modifies timeout to reflect the amount of
time not slept; most other implementations do not do this. This causes
problems both when Linux code which reads timeout is ported to other
operating systems, and when code is ported to Linux that reuses a
struct timeval for multiple selects in a loop without reinitializing
it. Consider timeout to be undefined after select returns.
Linux select() updates the timeout argument to reflect the time that has past.
Note that this is not portable across other systems (hence the warning in the OS X manual quoted above) but does work with Linux.
Gilad
Do not use select, try with fd larger than 1024 with your code and see what you will get.