Subject: Re: bug#20159: 24.4; url-retrieve invokes same callback twice with kill-buffer

From: Eli Zaretskii <[email-masked]>
Date: Sun, 22 Mar 2015 19:31:48 +0200

> From: Christopher Wellons <[email-masked]>
> Cc: [email-masked]
> Date: Sat, 21 Mar 2015 17:48:05 -0400
> 
> On Windows, url-retrieve doesn't return until the connection is either
> established or fails, making the call mostly synchronous. If the remote
> server takes 20 seconds to SYNACK, Emacs will lock up for 20 seconds
> (and C-g doesn't work either!). For example, currently the server at
> example.com doesn't seem to respond to anything, so try evaluating the
> following on Windows. For me, Emacs freezes for 21 seconds, until timing
> out, and the callback is never invoked.
> 
>     (url-retrieve "http://example.com:1/"; (lambda (_)))
> 
> On Linux it returns immediately and about a minute later the callback is
> invoked with an error status, timing out. I could call this 100 times in
> a loop without locking up Emacs. On Windows 7 on my computer, this locks
> up Emacs for half an hour, though hitting C-g will stop it within 21
> seconds (between loop iterations):
> 
>     ;; Try it if you dare!
>     (dotimes (_ 100)
>       (ignore-errors
>         (url-retrieve "http://example.com:1/"; (lambda (_)))))

Thanks for the example.

Due to some subtle technical issues with the 'select' emulation, the
':nowait' subfeature is turned off on Windows since more than 8 years
ago.  The result is that the 'connect' call is blocking, and I believe
this is what you see.

Volunteers are welcome to add support for non-blocking connections;
see these messages for the starting point:

  http://lists.gnu.org/archive/html/emacs-devel/2005-11/msg01586.html
  http://lists.gnu.org/archive/html/emacs-devel/2006-12/msg00873.html

However, the URL retrieval once the connection is established
generally works the same as on GNU/Linux: 'select' notifies the main
loop when some stuff is available for reading, and Emacs then reads
from every connection that has stuff ready.  The 'select' emulation
uses separate threads for each connection, so there's no serialization
there.  Therefore, if you see performance issues after the connection
is established, they are most probably due to other factor(s).

> Since it's synchronous on Windows, the error can be reported directly to
> the caller, which is what it does. The downside is awful performance and
> inconsistent error reporting (sometimes synchronously to the caller,
> sometimes asynchronously using the callback).

Errors for connection part are indeed reported directly.  As for
performance issues, see above: I see no direct relation between these
two, but maybe I'm missing something.

> I maintain the Elfeed RSS/Atom reader. I've noticed over the past 1.5
> years that its performance on Windows is very poor compared to Linux.
> It's bad enough that I've disabled parallel fetching of feeds on
> Windows. I see now that it's probably because url-retrieve isn't fully
> synchronous there. If I call url-retrieve four times in a row to fire
> off four connections, the TCP connections themselves will be performed
> serially between calls and not in parallel, as it is on Linux, so
> there's no point to doing so. They don't queue properly.

Again, this is true for the connection establishing part, but
shouldn't be so for the subsequent retrieval.

Thanks.