jupyter-ioloop: Fix for subprocess stdin buffering issue

This commit is contained in:
Nathaniel Nicandro 2019-07-01 17:56:26 -05:00
parent 909cdf3dd7
commit 02a0b470d9
2 changed files with 31 additions and 3 deletions

View file

@ -367,7 +367,7 @@ the local host, otherwise events are expected to be received on
STDIN. This is useful on Windows systems which don't allow STDIN. This is useful on Windows systems which don't allow
polling the STDIN file handle." polling the STDIN file handle."
(let ((stdin-form (let ((stdin-form
(if port `(let ((sock (zmq-socket ctx zmq-PULL))) (if port `(let ((sock (zmq-socket ctx zmq-PAIR)))
(prog1 sock (prog1 sock
(zmq-connect sock (format "tcp://127.0.0.1:%s" ,port)))) (zmq-connect sock (format "tcp://127.0.0.1:%s" ,port))))
'0)) '0))
@ -446,8 +446,20 @@ If BUFFER is non-nil it should be a buffer that will be used as
the IOLOOP subprocess buffer, see `zmq-start-process'." the IOLOOP subprocess buffer, see `zmq-start-process'."
(jupyter-ioloop-stop ioloop) (jupyter-ioloop-stop ioloop)
(let (stdin port) (let (stdin port)
(when (memq system-type '(windows-nt ms-dos cygwin)) ;; NOTE: A socket is used to read input from the parent process to avoid
(setq stdin (zmq-socket (zmq-current-context) zmq-PUSH)) ;; the stdin buffering done when using `read-from-minibuffer' in the
;; subprocess. When `noninteractive', `read-from-minibuffer' uses
;; `getc_unlocked' internally and `getc_unlocked' reads from the stdin FILE
;; object as opposed to reading directly from STDIN_FILENO. The problem is
;; that FILE objects are buffered streams which means that every message
;; the parent process sends does not necessarily correspond to a POLLIN
;; event on STDIN_FILENO in the subprocess. Since we only call
;; `read-from-minibuffer' when there is a POLLIN event on STDIN_FILENO
;; there is the potential that a message is waiting to be handled in the
;; buffer used by stdin which will only get handled if we send more
;; messages to the subprocess thereby creating more POLLIN events.
(when (or t (memq system-type '(windows-nt ms-dos cygwin)))
(setq stdin (zmq-socket (zmq-current-context) zmq-PAIR))
(setq port (zmq-bind-to-random-port stdin "tcp://127.0.0.1"))) (setq port (zmq-bind-to-random-port stdin "tcp://127.0.0.1")))
(let ((process (zmq-start-process (let ((process (zmq-start-process
(jupyter-ioloop--function ioloop (when stdin port)) (jupyter-ioloop--function ioloop (when stdin port))

View file

@ -1021,6 +1021,22 @@
(let ((result (read (buffer-string)))) (let ((result (read (buffer-string))))
(should (equal result `(stop-channel :shell)))))))) (should (equal result `(stop-channel :shell))))))))
(ert-deftest jupyter-zmq-channel-ioloop-send-fast ()
:tags '(ioloop queue)
;; :expected-result :failed
(jupyter-test-with-python-client client
(let ((jupyter-current-client client))
(jupyter-send-execute-request client :code "1 + 1")
(jupyter-send-execute-request client :code "1 + 1")
(jupyter-send-execute-request client :code "1 + 1")
(let ((req (jupyter-send-execute-request client :code "1 + 1")))
(should
(equal
(jupyter-message-data
(jupyter-wait-until-received :execute-result req jupyter-long-timeout)
:text/plain)
"2"))))))
;;; Completion ;;; Completion
(ert-deftest jupyter-completion-number-p () (ert-deftest jupyter-completion-number-p ()