Created attachment 6584 [details] C source code to test sem_timedwait function! gcc sem_timedwait.c -lrt -o sem_timedwait ./sem_timedwait sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=5us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=3us
What output do you expect? Your test program is never posting the semaphore, so of course it's going to timeout. Actually when running it I get EINTR rather than ETIMEDOUT; I'm using a fairly old kernel so perhaps they fixed the kernel bug where timed semaphores error out with EINTR when receiving a signal instead of properly restarting the syscall.
(In reply to comment #1) > What output do you expect? Your test program is never posting the semaphore, so > of course it's going to timeout. Actually when running it I get EINTR rather > than ETIMEDOUT; I'm using a fairly old kernel so perhaps they fixed the kernel > bug where timed semaphores error out with EINTR when receiving a signal instead > of properly restarting the syscall. Function return with errno 4 not 110. The expected output should like: sem_timedwait ret=-1 failed.errno=4 Real timeout=3948us sem_timedwait ret=-1 failed.errno=4 Real timeout=3929us sem_timedwait ret=-1 failed.errno=4 Real timeout=3958us sem_timedwait ret=-1 failed.errno=4 Real timeout=4149us sem_timedwait ret=-1 failed.errno=4 Real timeout=3967us sem_timedwait ret=-1 failed.errno=4 Real timeout=3818us sem_timedwait ret=-1 failed.errno=4 Real timeout=3978us sem_timedwait ret=-1 failed.errno=4 Real timeout=3965us sem_timedwait ret=-1 failed.errno=4 Real timeout=3994us sem_timedwait ret=-1 failed.errno=4 Real timeout=4035us sem_timedwait ret=-1 failed.errno=4 Real timeout=3910us sem_timedwait ret=-1 failed.errno=4 Real timeout=3982us sem_timedwait ret=-1 failed.errno=4 Real timeout=4045us sem_timedwait ret=-1 failed.errno=4 Real timeout=3892us Thanks!
(In reply to comment #1) > What output do you expect? Your test program is never posting the semaphore, so > of course it's going to timeout. Actually when running it I get EINTR rather > than ETIMEDOUT; I'm using a fairly old kernel so perhaps they fixed the kernel > bug where timed semaphores error out with EINTR when receiving a signal instead > of properly restarting the syscall. The abstimeout is correct (not earlier than now), so it should not return errno 110 (ETIMEDOUT). Thanks!
(In reply to comment #1) > What output do you expect? Your test program is never posting the semaphore, so > of course it's going to timeout. Actually when running it I get EINTR rather > than ETIMEDOUT; I'm using a fairly old kernel so perhaps they fixed the kernel > bug where timed semaphores error out with EINTR when receiving a signal instead > of properly restarting the syscall. Can you tell me which reason will result in errno 110 ? My abstimeout really greater than now. Thanks a lot!
As far as I can tell this report is invalid and is just a case of the reporter not understanding the interface. In particular, assuming the semaphore value is initially zero and it's never posted: 1. sem_timedwait should fail with ETIMEDOUT if the given time has already passed when it's called. 2. sem_timedwait should sleep until the given time, then fail with ETIMEDOUT, if the given time is in the future. 3. Signals that arrive during the wait should have no effect on sem_timedwait unless the handler was installed without the SA_RESTART option. Note that point 3 is not honored on most (all?) Linux versions; syscalls with timeouts get interrupted with EINTR even if the signal handler was installed with SA_RESTART. This is a bug in Linux, not glibc, and is impossible to fix at the libc level. If you still believe there's a glibc bug here, please explain what you expect the behavior to be in terms of the specification of the sem_timedwait function. As I've said, I can't see any bug...
(In reply to comment #5) > As far as I can tell this report is invalid and is just a case of the reporter > not understanding the interface. In particular, assuming the semaphore value is > initially zero and it's never posted: > 1. sem_timedwait should fail with ETIMEDOUT if the given time has already > passed when it's called. > 2. sem_timedwait should sleep until the given time, then fail with ETIMEDOUT, > if the given time is in the future. > 3. Signals that arrive during the wait should have no effect on sem_timedwait > unless the handler was installed without the SA_RESTART option. > Note that point 3 is not honored on most (all?) Linux versions; syscalls with > timeouts get interrupted with EINTR even if the signal handler was installed > with SA_RESTART. This is a bug in Linux, not glibc, and is impossible to fix at Maybe you should check the code in attachment. I have set a future time, and semaphore value is initially zero and it's never posted. So It should return with EINTR(errno=4). So anybody can tell me why it return with ETIMEOUT? > the libc level. > If you still believe there's a glibc bug here, please explain what you expect > the behavior to be in terms of the specification of the sem_timedwait function. > As I've said, I can't see any bug...
Your signal handler is not installed to be interrupting, so if sem_timedwait returns with EINTR (which it _DOES_ do on some/most Linux versions), that's a bug in the kernel. The expected result is ETIMEDOUT. Perhaps you expect signal() to have the legacy sysv behavior of installing interrupting signal handlers. This is not the case on glibc. If you want interrupting behavior, you must use sigaction() and omit the SA_RESTART flag. I still don't see any bug.
(In reply to comment #7) > Your signal handler is not installed to be interrupting, so if sem_timedwait > returns with EINTR (which it _DOES_ do on some/most Linux versions), that's a > bug in the kernel. The expected result is ETIMEDOUT. > Perhaps you expect signal() to have the legacy sysv behavior of installing > interrupting signal handlers. This is not the case on glibc. If you want > interrupting behavior, you must use sigaction() and omit the SA_RESTART flag. > I still don't see any bug. I have set the timeout = gettimeofday + 4000us , So if it return ETIMEDOUT, the real timeout should about 4000us. But the output is: #./sem_timedwait sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us I think the Real timeout should about 4000us, but it's 4us. Why? Thanks for your reply!
(In reply to comment #7) > Your signal handler is not installed to be interrupting, so if sem_timedwait > returns with EINTR (which it _DOES_ do on some/most Linux versions), that's a > bug in the kernel. The expected result is ETIMEDOUT. > Perhaps you expect signal() to have the legacy sysv behavior of installing > interrupting signal handlers. This is not the case on glibc. If you want > interrupting behavior, you must use sigaction() and omit the SA_RESTART flag. > I still don't see any bug. I have set the abstimeout = gettimeofday + 4000us , So if it return ETIMEDOUT, the real timeout should about 4000us. But the output is: #./sem_timedwait sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us I think the Real timeout should about 4000us, but it's 4us. Why? Thanks for your reply!
All your time calculation code is rather obfuscated and I haven't waded though it yet, but I suspect you're just confusing microseconds and nanoseconds. The fact that you're mixing interfaces that use timeval with ones that use timespec does not help. I would switch to using POSIX timespec interfaces for everything (timer_create for timers, clock_gettime for current time, etc.). If it really is timing out early, this is probably due to the Linux kernel bug for signal handlers interrupting syscalls with timeouts.
(In reply to comment #10) > All your time calculation code is rather obfuscated and I haven't waded though > it yet, but I suspect you're just confusing microseconds and nanoseconds. The > fact that you're mixing interfaces that use timeval with ones that use timespec > does not help. I would switch to using POSIX timespec interfaces for everything > (timer_create for timers, clock_gettime for current time, etc.). > If it really is timing out early, this is probably due to the Linux kernel bug > for signal handlers interrupting syscalls with timeouts. OK... Can you tell me why the output is different with the same system.(Linux 2.6.32) gcc sem_timedwait.c -lrt -o sem_timedwait One is like: #./sem_timedwait sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us sem_timedwait ret=-1 failed.errno=110 Real timeout=4us Another is like: #./sem_timedwait sem_timedwait ret=-1 failed.errno=4 Real timeout=3948us sem_timedwait ret=-1 failed.errno=4 Real timeout=3929us sem_timedwait ret=-1 failed.errno=4 Real timeout=3958us sem_timedwait ret=-1 failed.errno=4 Real timeout=4149us sem_timedwait ret=-1 failed.errno=4 Real timeout=3967us sem_timedwait ret=-1 failed.errno=4 Real timeout=3818us
You define errno as a local variable in the delay function, thus your program has undefined behaviour.
(In reply to comment #14) > You define errno as a local variable in the delay function, thus your program > has undefined behaviour. In my option, this is not the key reason! Thanks for your reply!
Rereading the comments thread, I finally understand what the reporter's misunderstanding is. He seems to think ETIMEDOUT is ONLY for the case where the abstime passed to sem_timedwait is _already_ in the past at the time of the call, and that something else (EINTR?) should happen if sem_timedwait successfully begins waiting but then times out. This expectation is simply wrong. ETIMEDOUT is the correct error for both cases (and of course formally they are not demonstrably different since it's not observable whether a thread has actually entered the sem_timedwait or delayed prior to entry to the function due to scheduling).