Charles-François Natali added the comment: Actually, I think urllib (actually ftplib) handles the timeout correctly.
Here's the result on my Linux box (replacing the server with localhost, with a firewall rule to drop packets to ftp port): $ ./python ~/edgartimeouttest3.py Open of ftp://localhost/daily-index failed after 60.09 seconds: <urlopen error ftp error: timeout('timed out',)> And indeed, here's what strace shows: $ strace -ttT ./python ~/edgartimeouttest3.py 23:15:46.953116 connect(3, {sa_family=AF_INET, sin_port=htons(21), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) <0.000066> 23:15:46.953257 poll([{fd=3, events=POLLOUT}], 1, 60000) = 0 (Timeout) <60.011497> See, we - correctly - pass 60s to poll()/select(). Now, I think I know what's going on in your case. It's likely that your TCP/IP stack settings have shorter timeouts than mine, so the kernel reports a timeout on the socket *before the timeout expires*: If I reduce the SYN retries limit (on Linux): # sysctl net.ipv4.tcp_syn_retries=1 net.ipv4.tcp_syn_retries = 1 I now get: $ ./python ~/edgartimeouttest3.py Open of ftp://localhost/daily-index failed after 3.03 seconds: <urlopen error ftp error: TimeoutError(110, 'Connection timed out')> 3s timeout, and yet, we still pass 60 seconds to poll(): 23:19:43.756823 connect(3, {sa_family=AF_INET, sin_port=htons(21), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) <0.000099> 23:19:43.757034 poll([{fd=3, events=POLLOUT}], 1, 60000) = 1 ([{fd=3, revents=POLLOUT|POLLERR|POLLHUP}]) <3.003306> In short, the kernel reports a timeout on the socket because it reached the maximum number of retries for SYN packets. And actually, you can check that the timeouts are correctly processed by passing a smaller value: if it's smaller than the TCP/IP retries limit, you'll get exactly the expected timeout. So I think it's not a Python bug, but rather an issue with your TCP/IP stack settings. On Linux, can you try to increase the following sysctls: # sysctl net.ipv4.tcp_syn_retries=7 # net.ipv4.tcp_retries1=7 And see if this solves your problem? (BTW, are you "the" John Nagle?) ---------- nosy: +neologix _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue18907> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com