Subject: 24.4; url-retrieve invokes same callback twice with kill-buffer
From: Christopher Wellons <[email-masked]>
To: [email-masked]
Date: Sat, 21 Mar 2015 16:46:16 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

Emacs 24.4.1 on x86_64 Linux, the callback passed to `url-retrieve' is
invoked twice if `kill-buffer' is called within the callback when the
status reports a connection failure. In the example below, it's assumed
this URL will reject the connection, which will cause `url-retrieve' to
asynchronously invoke the callback with an error status ("failed with
code 111\n"). The second invocation of the callback is synchronous with
the first invocation, because it's called recursively from within the
`kill-buffer' call. The error message the second time is "deleted\n".

    ;;; -*- lexical-binding: t; -*-
    (let ((calls 0))
      (url-retrieve "http://localhost:1/"
                    (lambda (_)
                      (assert (= 1 (cl-incf calls)))
                      (kill-buffer))))

When I eval the above expression, the assertion fails asynchronously.

    error in process sentinel: Assertion failed: (= 1 (cl-incf calls))

I expect the callback given to `url-retrieve' to never be invoked more
than once each time it's passed to `url-retrieve'. Ideally I expect it
to be called exactly once for each call to `url-retrieve', always
delivering errors asynchronously.

I also tested this on a Windows build of Emacs. The callback is invoked
zero times because the connection error is delivered synchronously at
the call to `url-retrieve' (which I now realize explains why connection
queuing doesn't work right on Windows). So even if the double-invoke
problem is fixed for Linux, the behavior still differs across platforms.