mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 09:14:18 +00:00
Jsonrpc: don't let remote endpoint requests go unanswered
Previously, 'quit' could cause remote endpoints to never get a reply and thus sometimes hang. Ensure we always reply. Also, give the application a chance to signal jsonrpc-error with the served code=32000, meaning "no error". * doc/lispref/text.texi (JSONRPC Overview): Rework section on request dispatchers. * lisp/jsonrpc.el (jsonrpc-connection-receive): Rework.
This commit is contained in:
parent
7ce09a741a
commit
adb605716f
2 changed files with 38 additions and 22 deletions
|
|
@ -6014,12 +6014,21 @@ must be a Lisp object that can be serialized as JSON (@pxref{Parsing
|
|||
JSON}). The result is forwarded to the server as the JSONRPC
|
||||
@code{result} object. A non-local return, achieved by calling the
|
||||
function @code{jsonrpc-error}, causes an error response to be sent to
|
||||
the server. The details of the accompanying JSONRPC @code{error}
|
||||
object are filled out with whatever was passed to
|
||||
@code{jsonrpc-error}. A non-local return triggered by an unexpected
|
||||
error of any other type also causes an error response to be sent
|
||||
(unless you have set @code{debug-on-error}, in which case this calls
|
||||
the Lisp debugger, @pxref{Error Debugging}).
|
||||
the server. A non-local return triggered by an unexpected error of any
|
||||
other type also causes a response to be sent. The debugger is never
|
||||
called (unless you have set @code{debug-on-error}, in which case the
|
||||
Lisp debugger may be called, @pxref{Error Debugging}).
|
||||
|
||||
The details of the accompanying JSONRPC @code{error} object are filled
|
||||
out automatically (in the case of unexpected errors) or with whatever
|
||||
was passed to @code{jsonrpc-error} (in the case of explicit calls).
|
||||
|
||||
Exceptionally, an explicit call to @code{jsonrpc-error} which sets
|
||||
@code{:code} to 32000 and @code{:data} to any JSON object has the
|
||||
meaning of ``no error'' and triggers a normal response to the remote
|
||||
endpoint with @code{result} being set to @code{:data}. This is useful
|
||||
if the application wants to treat some non-local exits such as user
|
||||
quits as benign.
|
||||
|
||||
@findex jsonrpc-convert-to-endpoint
|
||||
@findex jsonrpc-convert-from-endpoint
|
||||
|
|
|
|||
|
|
@ -327,22 +327,29 @@ dispatcher in CONN."
|
|||
(and method id)
|
||||
(let* ((debug-on-error (and debug-on-error
|
||||
(not jsonrpc-inhibit-debug-on-error)))
|
||||
(reply
|
||||
(condition-case-unless-debug _ignore
|
||||
reply)
|
||||
(unwind-protect
|
||||
(setq
|
||||
reply
|
||||
(condition-case oops
|
||||
`(:result ,(funcall rdispatcher conn (intern method)
|
||||
params))
|
||||
`(:result
|
||||
,(funcall rdispatcher conn (intern method) params))
|
||||
(jsonrpc-error
|
||||
(let* ((data (cdr oops))
|
||||
(code (alist-get 'jsonrpc-error-code data))
|
||||
(msg (alist-get 'jsonrpc-error-message
|
||||
(cdr oops))))
|
||||
(if (eq code 32000) ;; This means 'no error'
|
||||
(when-let* ((d (alist-get 'jsonrpc-error-data
|
||||
data)))
|
||||
`(:result ,d))
|
||||
`(:error
|
||||
(:code
|
||||
,(or (alist-get 'jsonrpc-error-code (cdr oops))
|
||||
-32603)
|
||||
:message ,(or (alist-get 'jsonrpc-error-message
|
||||
(cdr oops))
|
||||
"Internal error")))))
|
||||
(error
|
||||
'(:error (:code -32603 :message "Internal error"))))))
|
||||
(apply #'jsonrpc--reply conn id method reply)))
|
||||
(:code ,(or code -32603)
|
||||
:message ,(or msg "Internal error"))))))))
|
||||
(unless reply
|
||||
(setq reply
|
||||
`(:error (:code -32603 :message "Internal error"))))
|
||||
(apply #'jsonrpc--reply conn id method reply))))
|
||||
(;; A remote notification
|
||||
method
|
||||
(funcall ndispatcher conn (intern method) params))
|
||||
|
|
|
|||
Loading…
Reference in a new issue