alphapapa / plz.el

An HTTP library for Emacs
GNU General Public License v3.0
200 stars 11 forks source link

Selecting deleted buffer #48

Closed r0man closed 7 months ago

r0man commented 7 months ago

Hello,

when doing synchronous requests I sometimes get a Selecting deleted buffer error.

Steps to reproduce:

It does not happen always, but evaluating the following form often enough

(plz 'get "https://httpbin.org/user-agent")

will raise at some point the following error:

Debugger entered--Lisp error: (error "Selecting deleted buffer")
  set-buffer(#<killed buffer>)
  (save-current-buffer (set-buffer buffer) (let* ((pcase-0 #'(lambda (code) (let* (... ... ...) (let* ... ...))))) (cond ((member status '("finished\n" 0)) (let nil (goto-char (point-min)) (plz--skip-proxy-headers) (while (plz--skip-redirect-headers)) (let* ((val ...)) (if (let* ... ...) (let ... ... ... ...) (let nil ...))))) ((numberp status) (funcall pcase-0 status)) ((stringp status) (let* ((x64 (let ... ...))) (cond ((not ...) (funcall pcase-0 x64)) ((member status ...) (let ... ...)) (t (let ... ...))))) (t (let ((x63 status)) (error "No clause matching `%S'" x63))))))
  (unwind-protect (save-current-buffer (set-buffer buffer) (let* ((pcase-0 #'(lambda (code) (let* ... ...)))) (cond ((member status '("finished\n" 0)) (let nil (goto-char (point-min)) (plz--skip-proxy-headers) (while (plz--skip-redirect-headers)) (let* (...) (if ... ... ...)))) ((numberp status) (funcall pcase-0 status)) ((stringp status) (let* ((x64 ...)) (cond (... ...) (... ...) (t ...)))) (t (let ((x63 status)) (error "No clause matching `%S'" x63)))))) (let* ((finally (and t (process-get process :plz-finally)))) (if finally (funcall finally) nil)) (if (or (process-get process :plz-sync) (eq 'buffer (process-get process :plz-as))) nil (kill-buffer buffer)))
  plz--respond(#<process plz-request-curl> #<killed buffer> "finished\n")
  (if (process-get process :plz-sync) (plz--respond process buffer status) (run-at-time 0 nil #'plz--respond process buffer status))
  (let ((buffer (process-buffer process))) (if (process-get process :plz-sync) (plz--respond process buffer status) (run-at-time 0 nil #'plz--respond process buffer status)))
  (closure ((status . "finished\n") (process . #<process plz-request-curl>)) nil (let ((buffer (process-buffer process))) (if (process-get process :plz-sync) (plz--respond process buffer status) (run-at-time 0 nil #'plz--respond process buffer status))))()
  funcall((closure ((status . "finished\n") (process . #<process plz-request-curl>)) nil (let ((buffer (process-buffer process))) (if (process-get process :plz-sync) (plz--respond process buffer status) (run-at-time 0 nil #'plz--respond process buffer status)))))
  (cond ((member status '("interrupt\n" "killed\n" "finished\n")) (funcall pcase-0)) ((numberp status) (funcall pcase-0)) ((not (stringp status)) nil) ((string-match "exited abnormally with code \\([[:digit:]]+\\)" status) (funcall pcase-0)))
  (let* ((pcase-0 #'(lambda nil (let ((buffer ...)) (if (process-get process :plz-sync) (plz--respond process buffer status) (run-at-time 0 nil ... process buffer status)))))) (cond ((member status '("interrupt\n" "killed\n" "finished\n")) (funcall pcase-0)) ((numberp status) (funcall pcase-0)) ((not (stringp status)) nil) ((string-match "exited abnormally with code \\([[:digit:]]+\\)" status) (funcall pcase-0))))
  plz--sentinel(#<process plz-request-curl> "finished\n")
  kill-buffer(#<buffer  *plz-request-curl-stderr*>)
  (unwind-protect (condition-case nil (let ((inhibit-quit nil)) (if (and process stderr-process) nil (error "Process unexpectedly nil")) (while (accept-process-output process)) (while (accept-process-output stderr-process)) (if (eq :plz-result (process-get process :plz-result)) (progn (plz--sentinel process "finished\n") (if (eq :plz-result (process-get process :plz-result)) (progn (error "Plz: NO RESULT FROM PROCESS:%S  ARGS:%S" process rest))))) (let* ((val (process-get process :plz-result))) (if (progn (and (memq ... cl-struct-plz-error-tags) t)) (let ((data val)) (if (progn ... ...) (signal ... ...) (signal ... ...))) (let ((else val)) else)))) (quit (setq quit-flag t) (eval '(ignore nil) t))) (if (eq as 'buffer) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process)))
  (if sync-p (unwind-protect (condition-case nil (let ((inhibit-quit nil)) (if (and process stderr-process) nil (error "Process unexpectedly nil")) (while (accept-process-output process)) (while (accept-process-output stderr-process)) (if (eq :plz-result (process-get process :plz-result)) (progn (plz--sentinel process "finished\n") (if (eq :plz-result ...) (progn ...)))) (let* ((val (process-get process :plz-result))) (if (progn (and ... t)) (let (...) (if ... ... ...)) (let (...) else)))) (quit (setq quit-flag t) (eval '(ignore nil) t))) (if (eq as 'buffer) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process))) process)
  (let* ((data-arg (cond ((eq body-type 'binary) (let nil "--data-binary")) ((eq body-type 'text) (let nil "--data")) (t (let ((x32 body-type)) (error "No clause matching `%S'" x32))))) (curl-command-line-args (append plz-curl-default-args (list "--config" "-"))) (curl-config-header-args (let* ((--cl-var-- headers) (value nil) (key nil) (--cl-var-- nil)) (while (consp --cl-var--) (progn (setq value (car --cl-var--)) (setq key (car-safe ...))) (setq --cl-var-- (cons (cons "--header" ...) --cl-var--)) (setq --cl-var-- (cdr --cl-var--))) (nreverse --cl-var--))) (curl-config-args (append curl-config-header-args (list (cons "--url" url)) (if connect-timeout (progn (list (cons "--connect-timeout" ...)))) (if timeout (progn (list (cons "--max-time" ...)))) (cond ((eq method 'get) (let nil (list ...))) ((memq method '...) (let nil (list ... ... ...))) ((eq method 'delete) (let nil (list ... ...))) ((eq method 'head) (let nil (list ... ...)))))) (curl-config (let* ((--cl-var-- curl-config-args) (value nil) (key nil) (--cl-var-- "")) (while (consp --cl-var--) (progn (setq value (car --cl-var--)) (setq key (car-safe ...))) (setq --cl-var-- (concat --cl-var-- (format "%s \"%s\"\n" key value))) (setq --cl-var-- (cdr --cl-var--))) --cl-var--)) (decode (if (eq as 'binary) 'nil (let nil decode))) (default-directory temporary-file-directory) (process-buffer (generate-new-buffer " *plz-request-curl*")) (stderr-process (make-pipe-process :name "plz-request-curl-stderr" :buffer (generate-new-buffer " *plz-request-curl-stderr*") :noquery t :sentinel #'plz--stderr-sentinel)) (process (make-process :name "plz-request-curl" :buffer process-buffer :coding 'binary :command (append (list plz-curl-program) curl-command-line-args) :connection-type 'pipe :sentinel #'plz--sentinel :stderr stderr-process :noquery noquery)) sync-p) (if (eq 'sync then) (progn (progn (setq sync-p t) (setq then #'(lambda (result) (process-put process :plz-result result))) (setq else nil)))) (progn (let* ((v process)) (process-put v :plz-then (let* ((pcase-0 #'...)) (cond ((memq as ...) (let nil ...)) ((eq as ...) (let nil ...)) ((eq as ...) (let nil ...)) ((eq as ...) (let nil ...)) ((consp as) (let* ... ...)) ((functionp as) (funcall pcase-0)) (t (let ... ...)))))) (let* ((v process)) (process-put v :plz-else else)) (let* ((v process)) (process-put v :plz-finally finally)) (let* ((v process)) (process-put v :plz-sync sync-p)) (let* ((v process)) (process-put v :plz-args (apply #'list method url rest))) (let* ((v process)) (process-put v :plz-result :plz-result))) (process-send-string process curl-config) (if body (progn (cond ((stringp body) (process-send-string process body)) ((bufferp body) (save-current-buffer (set-buffer body) (process-send-region process (point-min) (point-max))))))) (process-send-eof process) (if sync-p (unwind-protect (condition-case nil (let ((inhibit-quit nil)) (if (and process stderr-process) nil (error "Process unexpectedly nil")) (while (accept-process-output process)) (while (accept-process-output stderr-process)) (if (eq :plz-result (process-get process :plz-result)) (progn (plz--sentinel process "finished\n") (if ... ...))) (let* ((val ...)) (if (progn ...) (let ... ...) (let ... else)))) (quit (setq quit-flag t) (eval '(ignore nil) t))) (if (eq as 'buffer) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process))) process))
  (progn (setq decode (if (and decode-s (not decode)) nil decode)) (setq headers (cons (cons "Expect" "") headers)) (let* ((data-arg (cond ((eq body-type 'binary) (let nil "--data-binary")) ((eq body-type 'text) (let nil "--data")) (t (let (...) (error "No clause matching `%S'" x32))))) (curl-command-line-args (append plz-curl-default-args (list "--config" "-"))) (curl-config-header-args (let* ((--cl-var-- headers) (value nil) (key nil) (--cl-var-- nil)) (while (consp --cl-var--) (progn (setq value ...) (setq key ...)) (setq --cl-var-- (cons ... --cl-var--)) (setq --cl-var-- (cdr --cl-var--))) (nreverse --cl-var--))) (curl-config-args (append curl-config-header-args (list (cons "--url" url)) (if connect-timeout (progn (list ...))) (if timeout (progn (list ...))) (cond ((eq method ...) (let nil ...)) ((memq method ...) (let nil ...)) ((eq method ...) (let nil ...)) ((eq method ...) (let nil ...))))) (curl-config (let* ((--cl-var-- curl-config-args) (value nil) (key nil) (--cl-var-- "")) (while (consp --cl-var--) (progn (setq value ...) (setq key ...)) (setq --cl-var-- (concat --cl-var-- ...)) (setq --cl-var-- (cdr --cl-var--))) --cl-var--)) (decode (if (eq as 'binary) 'nil (let nil decode))) (default-directory temporary-file-directory) (process-buffer (generate-new-buffer " *plz-request-curl*")) (stderr-process (make-pipe-process :name "plz-request-curl-stderr" :buffer (generate-new-buffer " *plz-request-curl-stderr*") :noquery t :sentinel #'plz--stderr-sentinel)) (process (make-process :name "plz-request-curl" :buffer process-buffer :coding 'binary :command (append (list plz-curl-program) curl-command-line-args) :connection-type 'pipe :sentinel #'plz--sentinel :stderr stderr-process :noquery noquery)) sync-p) (if (eq 'sync then) (progn (progn (setq sync-p t) (setq then #'(lambda ... ...)) (setq else nil)))) (progn (let* ((v process)) (process-put v :plz-then (let* ((pcase-0 ...)) (cond (... ...) (... ...) (... ...) (... ...) (... ...) (... ...) (t ...))))) (let* ((v process)) (process-put v :plz-else else)) (let* ((v process)) (process-put v :plz-finally finally)) (let* ((v process)) (process-put v :plz-sync sync-p)) (let* ((v process)) (process-put v :plz-args (apply #'list method url rest))) (let* ((v process)) (process-put v :plz-result :plz-result))) (process-send-string process curl-config) (if body (progn (cond ((stringp body) (process-send-string process body)) ((bufferp body) (save-current-buffer (set-buffer body) (process-send-region process ... ...)))))) (process-send-eof process) (if sync-p (unwind-protect (condition-case nil (let ((inhibit-quit nil)) (if (and process stderr-process) nil (error "Process unexpectedly nil")) (while (accept-process-output process)) (while (accept-process-output stderr-process)) (if (eq :plz-result ...) (progn ... ...)) (let* (...) (if ... ... ...))) (quit (setq quit-flag t) (eval '... t))) (if (eq as 'buffer) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process))) process)))
  (progn (let ((--cl-keys-- rest)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '(:headers :body :else :finally :noquery :as :then :body-type :decode :connect-timeout :timeout :allow-other-keys)) (if (cdr --cl-keys--) nil (error "Missing argument for %s" (car --cl-keys--))) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq ... rest))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:headers :body :el..." (car --cl-keys--)))))) (progn (setq decode (if (and decode-s (not decode)) nil decode)) (setq headers (cons (cons "Expect" "") headers)) (let* ((data-arg (cond ((eq body-type ...) (let nil "--data-binary")) ((eq body-type ...) (let nil "--data")) (t (let ... ...)))) (curl-command-line-args (append plz-curl-default-args (list "--config" "-"))) (curl-config-header-args (let* ((--cl-var-- headers) (value nil) (key nil) (--cl-var-- nil)) (while (consp --cl-var--) (progn ... ...) (setq --cl-var-- ...) (setq --cl-var-- ...)) (nreverse --cl-var--))) (curl-config-args (append curl-config-header-args (list (cons "--url" url)) (if connect-timeout (progn ...)) (if timeout (progn ...)) (cond (... ...) (... ...) (... ...) (... ...)))) (curl-config (let* ((--cl-var-- curl-config-args) (value nil) (key nil) (--cl-var-- "")) (while (consp --cl-var--) (progn ... ...) (setq --cl-var-- ...) (setq --cl-var-- ...)) --cl-var--)) (decode (if (eq as 'binary) 'nil (let nil decode))) (default-directory temporary-file-directory) (process-buffer (generate-new-buffer " *plz-request-curl*")) (stderr-process (make-pipe-process :name "plz-request-curl-stderr" :buffer (generate-new-buffer " *plz-request-curl-stderr*") :noquery t :sentinel #'plz--stderr-sentinel)) (process (make-process :name "plz-request-curl" :buffer process-buffer :coding 'binary :command (append (list plz-curl-program) curl-command-line-args) :connection-type 'pipe :sentinel #'plz--sentinel :stderr stderr-process :noquery noquery)) sync-p) (if (eq 'sync then) (progn (progn (setq sync-p t) (setq then #'...) (setq else nil)))) (progn (let* ((v process)) (process-put v :plz-then (let* (...) (cond ... ... ... ... ... ... ...)))) (let* ((v process)) (process-put v :plz-else else)) (let* ((v process)) (process-put v :plz-finally finally)) (let* ((v process)) (process-put v :plz-sync sync-p)) (let* ((v process)) (process-put v :plz-args (apply #'list method url rest))) (let* ((v process)) (process-put v :plz-result :plz-result))) (process-send-string process curl-config) (if body (progn (cond ((stringp body) (process-send-string process body)) ((bufferp body) (save-current-buffer ... ...))))) (process-send-eof process) (if sync-p (unwind-protect (condition-case nil (let (...) (if ... nil ...) (while ...) (while ...) (if ... ...) (let* ... ...)) (quit (setq quit-flag t) (eval ... t))) (if (eq as 'buffer) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process))) process))))
  (let* ((headers (car (cdr (plist-member rest ':headers)))) (body (car (cdr (plist-member rest ':body)))) (else (car (cdr (plist-member rest ':else)))) (finally (car (cdr (plist-member rest ':finally)))) (noquery (car (cdr (plist-member rest ':noquery)))) (as (car (cdr (or (plist-member rest ':as) '(nil string))))) (then (car (cdr (or (plist-member rest ':then) '(nil sync))))) (body-type (car (cdr (or (plist-member rest ':body-type) '(nil text))))) (decode-s (plist-member rest ':decode)) (decode (if decode-s (prog1 (car (cdr decode-s)) (setq decode-s t)) t)) (connect-timeout (car (cdr (or (plist-member rest ':connect-timeout) (list nil plz-connect-timeout))))) (timeout (car (cdr (or (plist-member rest ':timeout) (list nil plz-timeout)))))) (progn (let ((--cl-keys-- rest)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '...) (if (cdr --cl-keys--) nil (error "Missing argument for %s" ...)) (setq --cl-keys-- (cdr ...))) ((car (cdr ...)) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:headers :body :el..." (car --cl-keys--)))))) (progn (setq decode (if (and decode-s (not decode)) nil decode)) (setq headers (cons (cons "Expect" "") headers)) (let* ((data-arg (cond (... ...) (... ...) (t ...))) (curl-command-line-args (append plz-curl-default-args (list "--config" "-"))) (curl-config-header-args (let* (... ... ... ...) (while ... ... ... ...) (nreverse --cl-var--))) (curl-config-args (append curl-config-header-args (list ...) (if connect-timeout ...) (if timeout ...) (cond ... ... ... ...))) (curl-config (let* (... ... ... ...) (while ... ... ... ...) --cl-var--)) (decode (if (eq as ...) 'nil (let nil decode))) (default-directory temporary-file-directory) (process-buffer (generate-new-buffer " *plz-request-curl*")) (stderr-process (make-pipe-process :name "plz-request-curl-stderr" :buffer (generate-new-buffer " *plz-request-curl-stderr*") :noquery t :sentinel #'plz--stderr-sentinel)) (process (make-process :name "plz-request-curl" :buffer process-buffer :coding 'binary :command (append ... curl-command-line-args) :connection-type 'pipe :sentinel #'plz--sentinel :stderr stderr-process :noquery noquery)) sync-p) (if (eq 'sync then) (progn (progn (setq sync-p t) (setq then ...) (setq else nil)))) (progn (let* ((v process)) (process-put v :plz-then (let* ... ...))) (let* ((v process)) (process-put v :plz-else else)) (let* ((v process)) (process-put v :plz-finally finally)) (let* ((v process)) (process-put v :plz-sync sync-p)) (let* ((v process)) (process-put v :plz-args (apply ... method url rest))) (let* ((v process)) (process-put v :plz-result :plz-result))) (process-send-string process curl-config) (if body (progn (cond (... ...) (... ...)))) (process-send-eof process) (if sync-p (unwind-protect (condition-case nil (let ... ... ... ... ... ...) (quit ... ...)) (if (eq as ...) nil (kill-buffer process-buffer)) (kill-buffer (process-buffer stderr-process))) process)))))
  plz(get "https://httpbin.org/user-agent")
  (progn (plz 'get "https://httpbin.org/user-agent"))
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  command-execute(eval-last-sexp)

I can reproduce this reliably with:

(dotimes (i 50)
  (message "%s" i)
  (plz 'get "https://httpbin.org/user-agent"))

I found the following issue that has/had the same/similar problem:

https://github.com/alphapapa/plz.el/issues/23

Any ideas?

alphapapa commented 7 months ago

No, AFAIK that was solved a long time ago. I am unable to reproduce it in a clean configuration using your example code on Emacs 29.1 with plz v0.7.

r0man commented 7 months ago

Well, I should have tried a clean Emacs before posting. Can't reproduce it there either. I will see if I can figure out what is causing this. I will look at kill-buffer-hook. Do you have any other functions/hooks in mind that could interfere here?

alphapapa commented 7 months ago

No, but Emacs's process-handling is not exactly straightforward, and I'm no expert on it. I can only recommend the Elisp manual section and, if nothing else, looking through process.c.