New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
socket.settimeout(5.0) does not have any effect #67540
Comments
After setting socket.settimeout(5.0), socket.send() returns immediately, instead of returning after specified timeout. Steps to reproduce: Open two python interpreters. In the first one (the receiver) execute:
In the second one (the sender) execute:
Then run the following command 11 times:
On the 12 run command will block. This happens because datagram sockets queue on Linux is 11 messages long. Interrupt the command. So far so good. Then set sender socket timeout:
Expected behavior: s.sendto() should block for a 5 seconds and THEN raise error 11 (EAGAIN/EWOULDBLOCK). Actual behavior: s.sendto() raises the error IMMEDIATELY. >>> s.sendto("msg", "test.sock")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.error: [Errno 11] Resource temporarily unavailable So, in fact, s.settimeout(5.0) does not have any effect. I think that problem is that settimeout() sets the socket to the non-blocking mode (docs say: "Timeout mode internally sets the socket in non-blocking mode."). As described here setting timeout on non-blocking sockets is impossible. In fact, when I set timeout manually with setsockopt(), everything works as expected:
Now s.sendto() raises the error after 5 seconds, as expected. |
The way socket timeouts are implemented is by using select() to determine whether the socket is ready for read/write. In this case, select() probably marks the socket ready even though the queue is full, which later raises EAGAIN. About SO_SNDTIMEO and SO_RCVTIMEO, POSIX says "it is implementation-defined whether the SO_SNDTIMEO option can be set". Also, they would not necessarily apply to other operations such as accept(). |
Indeed, and this looks like a kernel bug. Working as expected on a RHEL6: $ python /tmp/test_unix_sock_timeout.py
('sending ', 0)
took 0.000s
('sending ', 1)
took 0.000s
('sending ', 2)
took 0.000s
('sending ', 3)
took 0.000s
('sending ', 4)
took 0.000s
('sending ', 5)
took 0.000s
('sending ', 6)
took 0.000s
('sending ', 7)
took 0.000s
('sending ', 8)
took 0.000s
('sending ', 9)
took 0.000s
('sending ', 10)
took 0.000s
('sending ', 11)
took 1.000s
Traceback (most recent call last):
File "/tmp/test_unix_sock_timeout.py", line 17, in <module>
s.sendto("hello", SOCKNAME)
socket.timeout: timed out
Exactly, the current way timeouts are implemented ar The Right Way, IMO. |
The test script works on Ubuntu 14.10 as well. |
Does not work on Debian 7 Wheezy, kernel 3.2.65. $ python test.py
('sending ', 0)
took 0.000s
('sending ', 1)
took 0.000s
('sending ', 2)
took 0.000s
('sending ', 3)
took 0.000s
('sending ', 4)
took 0.000s
('sending ', 5)
took 0.000s
('sending ', 6)
took 0.000s
('sending ', 7)
took 0.000s
('sending ', 8)
took 0.000s
('sending ', 9)
took 0.000s
('sending ', 10)
took 0.000s
('sending ', 11)
took 0.000s
Traceback (most recent call last):
File "test.py", line 17, in <module>
s.sendto("hello", SOCKNAME)
socket.error: [Errno 11] Resource temporarily unavailable $ uname -a
Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.65-1+deb7u1 x86_64 GNU/Linux |
It's a kernel bug closing (working fine on my Debian wheezy with a more recent kernel BTW). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: