aboutsummaryrefslogtreecommitdiffstats
path: root/test/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2021-07-12 13:58:28 +0200
committerMattias EngdegÄrd2021-07-13 19:07:41 +0200
commit7a803ecd3d455999cfc9266fa219d58109fac786 (patch)
treee24f82c78991b57c2144240a2d831833e240ae60 /test/src
parenta41f585bf111b239601ca7d915994fed600852af (diff)
downloademacs-7a803ecd3d455999cfc9266fa219d58109fac786.tar.gz
emacs-7a803ecd3d455999cfc9266fa219d58109fac786.zip
Block TLS handshake until TCP connection established
If a TLS handshake is attempted before the completion of an asynchronous TCP connection has been ascertained, our local state will not be set up correctly for further progress and the sentinel "open" event will never be sent. This can occur if sufficient time passes after the initiation of an async TCP connection so that by the time `wait_reading_process_output` is called, the connection has already been established on the TCP level. This somewhat timing-sensitive bug has plagued HTTPS connections on some platforms, notably macOS, for a long time (bug#49449). * src/process.c (wait_reading_process_output): Gate the TLS handshake by the NON_BLOCKING_CONNECT_FD flag. The flag will be cleared as soon as the TCP socket is found to be writable. * test/src/process-tests.el (process-async-https-with-delay): New test.
Diffstat (limited to 'test/src')
-rw-r--r--test/src/process-tests.el30
1 files changed, 30 insertions, 0 deletions
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index 1774f2fc74e..9bab523708e 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -28,6 +28,7 @@
28(require 'puny) 28(require 'puny)
29(require 'subr-x) 29(require 'subr-x)
30(require 'dns) 30(require 'dns)
31(require 'url-http)
31 32
32;; Timeout in seconds; the test fails if the timeout is reached. 33;; Timeout in seconds; the test fails if the timeout is reached.
33(defvar process-test-sentinel-wait-timeout 2.0) 34(defvar process-test-sentinel-wait-timeout 2.0)
@@ -916,5 +917,34 @@ Return nil if FILENAME doesn't exist."
916 ;; ...and the change description should be "interrupt". 917 ;; ...and the change description should be "interrupt".
917 (should (equal '("interrupt\n") events))))) 918 (should (equal '("interrupt\n") events)))))
918 919
920(ert-deftest process-async-https-with-delay ()
921 "Bug#49449: asynchronous TLS connection with delayed completion."
922 (skip-unless (and internet-is-working (gnutls-available-p)))
923 (let* ((status nil)
924 (buf (url-http
925 #s(url "https" nil nil "elpa.gnu.org" nil
926 "/packages/archive-contents" nil nil t silent t t)
927 (lambda (s) (setq status s))
928 '(nil) nil 'tls)))
929 (unwind-protect
930 (progn
931 ;; Busy-wait for 1 s to allow for the TCP connection to complete.
932 (let ((delay 1.0)
933 (t0 (float-time)))
934 (while (< (float-time) (+ t0 delay))))
935 ;; Wait for the entire operation to finish.
936 (let ((limit 4.0)
937 (t0 (float-time)))
938 (while (and (null status)
939 (< (float-time) (+ t0 limit)))
940 (sit-for 0.1)))
941 (should status)
942 (should-not (assq :error status))
943 (should buf)
944 (should (> (buffer-size buf) 0))
945 )
946 (when buf
947 (kill-buffer buf)))))
948
919(provide 'process-tests) 949(provide 'process-tests)
920;;; process-tests.el ends here 950;;; process-tests.el ends here