* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
@ 2024-05-02 19:37 Spencer Baugh
2024-05-04 1:09 ` Dmitry Gutov
0 siblings, 1 reply; 12+ messages in thread
From: Spencer Baugh @ 2024-05-02 19:37 UTC (permalink / raw)
To: 70724; +Cc: dmity, app-emacs-dev
In some project /home/foo/proj, with pretty much any LSP server:
1. In /home/foo/proj, M-x eglot, starting some LSP server
2. Delete the directory /home/foo/proj
3. The LSP server will crash/exit
4. The process sentinel for the server will run, running
eglot--on-shutdown which by default will call eglot-reconnect
5. eglot-reconnect extracts the saved project instance out of the
server, which has a root directory which no longer exists, and calls
eglot--connect with it
6. eglot--connect calls project-name on a nonexistent project instance,
which may fail with an error depending on the project implementation
(I have a custom project implementation, but I think this can happen
with project-vc too)
7. This causes the process sentinel to error.
I think the right fix is probably for eglot--on-shutdown (or maybe
eglot-reconnect) to call (project-current nil (project-root pr)) to find
the new project instance. If that returns nil, the project has
disappeared, and eglot should just not try to reconnect. This also
would make eglot behave better if the project layout changes (e.g. if
there are nested projects).
Alternatively, maybe eglot--on-shutdown shouldn't automatically
reconnect in the first place? Maybe reconnection should happen
automatically only when some specific buffer tries to interact with the
LSP - then it can run project-current in the context of that specific
buffer, and see there's no project, and fail. Plus, if the user kills
all the buffers in the project (possibly with project-kill-buffers)
before deleting it, this approach would entirely avoid the unnecessary
eglot reconnection attempt.
In GNU Emacs 29.2.50 (build 2, x86_64-pc-linux-gnu, X toolkit, cairo
version 1.15.12, Xaw scroll bars) of 2024-04-25 built on
igm-qws-u22796a
Repository revision: d07451c1f8053fa355d091351a614f232995ab8c
Repository branch: emacs-29
Windowing system distributor 'The X.Org Foundation', version 11.0.12011000
System Description: Rocky Linux 8.9 (Green Obsidian)
Configured using:
'configure -C --with-x-toolkit=lucid --with-gif=ifavailable'
Configured features:
CAIRO DBUS FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG JSON
LIBSELINUX LIBSYSTEMD LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG RSVG
SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS X11 XDBE XIM
XINPUT2 XPM LUCID ZLIB
Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
Major mode: ELisp/l
Minor modes in effect:
repeat-mode: t
delete-selection-mode: t
global-so-long-mode: t
pixel-scroll-precision-mode: t
jane-fe-minor-mode: t
jane-fe-jenga-minor-mode: t
editorconfig-mode: t
dired-omit-mode: t
which-function-mode: t
global-git-commit-mode: t
magit-auto-revert-mode: t
shell-dirtrack-mode: t
server-mode: t
savehist-mode: t
save-place-mode: t
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tab-bar-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
context-menu-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
line-number-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Features:
(magit-patch make-mode doctor texinfo texinfo-loaddefs completion
emacs-news-mode latexenc mode-local minibuf-eldef ...)
Memory information:
((conses 16 4170589 532507)
(symbols 48 67528 55)
(strings 32 645610 32608)
(string-bytes 1 31944500)
(vectors 16 203742)
(vector-slots 8 4053669 619438)
(floats 8 1045 1428)
(intervals 56 410065 1774)
(buffers 976 767))
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-05-02 19:37 bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted Spencer Baugh
@ 2024-05-04 1:09 ` Dmitry Gutov
2024-05-18 8:31 ` Eli Zaretskii
2024-06-06 20:36 ` Dmitry Gutov
0 siblings, 2 replies; 12+ messages in thread
From: Dmitry Gutov @ 2024-05-04 1:09 UTC (permalink / raw)
To: Spencer Baugh, 70724; +Cc: app-emacs-dev
Hi Spencer,
On 02/05/2024 22:37, Spencer Baugh wrote:
>
> In some project /home/foo/proj, with pretty much any LSP server:
>
> 1. In /home/foo/proj, M-x eglot, starting some LSP server
>
> 2. Delete the directory /home/foo/proj
>
> 3. The LSP server will crash/exit
>
> 4. The process sentinel for the server will run, running
> eglot--on-shutdown which by default will call eglot-reconnect
>
> 5. eglot-reconnect extracts the saved project instance out of the
> server, which has a root directory which no longer exists, and calls
> eglot--connect with it
>
> 6. eglot--connect calls project-name on a nonexistent project instance,
> which may fail with an error depending on the project implementation
> (I have a custom project implementation, but I think this can happen
> with project-vc too)
>
> 7. This causes the process sentinel to error.
>
> I think the right fix is probably for eglot--on-shutdown (or maybe
> eglot-reconnect) to call (project-current nil (project-root pr)) to find
> the new project instance. If that returns nil, the project has
> disappeared, and eglot should just not try to reconnect. This also
> would make eglot behave better if the project layout changes (e.g. if
> there are nested projects).
I think I like this solution (as long as the nil value returned by
project-current on this step is appropriately handled).
Something like:
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 6896baf30ce..7b2461c3ce6 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1426,11 +1426,15 @@ eglot-reconnect
(interactive (list (eglot--current-server-or-lose) t))
(when (jsonrpc-running-p server)
(ignore-errors (eglot-shutdown server interactive nil
'preserve-buffers)))
- (eglot--connect (eglot--major-modes server)
- (eglot--project server)
- (eieio-object-class-name server)
- (eglot--saved-initargs server)
- (eglot--language-ids server))
+ (let* ((root (project-root (eglot--project server)))
+ (project (project-current nil root)))
+ (if (not project)
+ (eglot--error "Project in `%s' is gone!" root)
+ (eglot--connect (eglot--major-modes server)
+ project
+ (eieio-object-class-name server)
+ (eglot--saved-initargs server)
+ (eglot--language-ids server))))
(eglot--message "Reconnected!"))
(defvar eglot--managed-mode) ; forward decl
Though it also raises a question about the caching strategy for VC-Aware
project backend. At the moment is associates a project with a directory
more or less indefinitely, and this is a case to watch out for.
> Alternatively, maybe eglot--on-shutdown shouldn't automatically
> reconnect in the first place? Maybe reconnection should happen
> automatically only when some specific buffer tries to interact with the
> LSP - then it can run project-current in the context of that specific
> buffer, and see there's no project, and fail. Plus, if the user kills
> all the buffers in the project (possibly with project-kill-buffers)
> before deleting it, this approach would entirely avoid the unnecessary
> eglot reconnection attempt.
This also sounds good, though it'd probably require more changes
overall. Additionally, perhaps I'd change the association from (server
-> project) to (server -> project-root), relying on the project
backends' internal caches to fetch the project value whenever it's
needed. That might be the most reliable approach. Perhaps the slowest in
theory, but hopefully not noticeably so.
^ permalink raw reply related [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-05-04 1:09 ` Dmitry Gutov
@ 2024-05-18 8:31 ` Eli Zaretskii
2024-05-19 15:08 ` Dmitry Gutov
2024-06-06 20:36 ` Dmitry Gutov
1 sibling, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2024-05-18 8:31 UTC (permalink / raw)
To: sbaugh, Dmitry Gutov; +Cc: app-emacs-dev, 70724
Ping! Can we make some progress here?
> Cc: app-emacs-dev@janestreet.com
> Date: Sat, 4 May 2024 04:09:48 +0300
> From: Dmitry Gutov <dmitry@gutov.dev>
>
> Hi Spencer,
>
> On 02/05/2024 22:37, Spencer Baugh wrote:
> >
> > In some project /home/foo/proj, with pretty much any LSP server:
> >
> > 1. In /home/foo/proj, M-x eglot, starting some LSP server
> >
> > 2. Delete the directory /home/foo/proj
> >
> > 3. The LSP server will crash/exit
> >
> > 4. The process sentinel for the server will run, running
> > eglot--on-shutdown which by default will call eglot-reconnect
> >
> > 5. eglot-reconnect extracts the saved project instance out of the
> > server, which has a root directory which no longer exists, and calls
> > eglot--connect with it
> >
> > 6. eglot--connect calls project-name on a nonexistent project instance,
> > which may fail with an error depending on the project implementation
> > (I have a custom project implementation, but I think this can happen
> > with project-vc too)
> >
> > 7. This causes the process sentinel to error.
> >
> > I think the right fix is probably for eglot--on-shutdown (or maybe
> > eglot-reconnect) to call (project-current nil (project-root pr)) to find
> > the new project instance. If that returns nil, the project has
> > disappeared, and eglot should just not try to reconnect. This also
> > would make eglot behave better if the project layout changes (e.g. if
> > there are nested projects).
>
> I think I like this solution (as long as the nil value returned by
> project-current on this step is appropriately handled).
>
> Something like:
>
> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
> index 6896baf30ce..7b2461c3ce6 100644
> --- a/lisp/progmodes/eglot.el
> +++ b/lisp/progmodes/eglot.el
> @@ -1426,11 +1426,15 @@ eglot-reconnect
> (interactive (list (eglot--current-server-or-lose) t))
> (when (jsonrpc-running-p server)
> (ignore-errors (eglot-shutdown server interactive nil
> 'preserve-buffers)))
> - (eglot--connect (eglot--major-modes server)
> - (eglot--project server)
> - (eieio-object-class-name server)
> - (eglot--saved-initargs server)
> - (eglot--language-ids server))
> + (let* ((root (project-root (eglot--project server)))
> + (project (project-current nil root)))
> + (if (not project)
> + (eglot--error "Project in `%s' is gone!" root)
> + (eglot--connect (eglot--major-modes server)
> + project
> + (eieio-object-class-name server)
> + (eglot--saved-initargs server)
> + (eglot--language-ids server))))
> (eglot--message "Reconnected!"))
>
> (defvar eglot--managed-mode) ; forward decl
>
>
> Though it also raises a question about the caching strategy for VC-Aware
> project backend. At the moment is associates a project with a directory
> more or less indefinitely, and this is a case to watch out for.
>
> > Alternatively, maybe eglot--on-shutdown shouldn't automatically
> > reconnect in the first place? Maybe reconnection should happen
> > automatically only when some specific buffer tries to interact with the
> > LSP - then it can run project-current in the context of that specific
> > buffer, and see there's no project, and fail. Plus, if the user kills
> > all the buffers in the project (possibly with project-kill-buffers)
> > before deleting it, this approach would entirely avoid the unnecessary
> > eglot reconnection attempt.
>
> This also sounds good, though it'd probably require more changes
> overall. Additionally, perhaps I'd change the association from (server
> -> project) to (server -> project-root), relying on the project
> backends' internal caches to fetch the project value whenever it's
> needed. That might be the most reliable approach. Perhaps the slowest in
> theory, but hopefully not noticeably so.
>
>
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-05-18 8:31 ` Eli Zaretskii
@ 2024-05-19 15:08 ` Dmitry Gutov
2024-11-21 19:46 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <ierplmotmxh.fsf@janestreet.com>
0 siblings, 2 replies; 12+ messages in thread
From: Dmitry Gutov @ 2024-05-19 15:08 UTC (permalink / raw)
To: Eli Zaretskii, sbaugh, João Távora; +Cc: app-emacs-dev, 70724
Seems like we could use Eglot's maintainer's input.
On 18/05/2024 11:31, Eli Zaretskii wrote:
> Ping! Can we make some progress here?
>
>> Cc: app-emacs-dev@janestreet.com
>> Date: Sat, 4 May 2024 04:09:48 +0300
>> From: Dmitry Gutov <dmitry@gutov.dev>
>>
>> Hi Spencer,
>>
>> On 02/05/2024 22:37, Spencer Baugh wrote:
>> >
>> > In some project /home/foo/proj, with pretty much any LSP server:
>> >
>> > 1. In /home/foo/proj, M-x eglot, starting some LSP server
>> >
>> > 2. Delete the directory /home/foo/proj
>> >
>> > 3. The LSP server will crash/exit
>> >
>> > 4. The process sentinel for the server will run, running
>> > eglot--on-shutdown which by default will call eglot-reconnect
>> >
>> > 5. eglot-reconnect extracts the saved project instance out of the
>> > server, which has a root directory which no longer exists, and calls
>> > eglot--connect with it
>> >
>> > 6. eglot--connect calls project-name on a nonexistent project instance,
>> > which may fail with an error depending on the project implementation
>> > (I have a custom project implementation, but I think this can happen
>> > with project-vc too)
>> >
>> > 7. This causes the process sentinel to error.
>> >
>> > I think the right fix is probably for eglot--on-shutdown (or maybe
>> > eglot-reconnect) to call (project-current nil (project-root pr)) to find
>> > the new project instance. If that returns nil, the project has
>> > disappeared, and eglot should just not try to reconnect. This also
>> > would make eglot behave better if the project layout changes (e.g. if
>> > there are nested projects).
>>
>> I think I like this solution (as long as the nil value returned by
>> project-current on this step is appropriately handled).
>>
>> Something like:
>>
>> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
>> index 6896baf30ce..7b2461c3ce6 100644
>> --- a/lisp/progmodes/eglot.el
>> +++ b/lisp/progmodes/eglot.el
>> @@ -1426,11 +1426,15 @@ eglot-reconnect
>> (interactive (list (eglot--current-server-or-lose) t))
>> (when (jsonrpc-running-p server)
>> (ignore-errors (eglot-shutdown server interactive nil
>> 'preserve-buffers)))
>> - (eglot--connect (eglot--major-modes server)
>> - (eglot--project server)
>> - (eieio-object-class-name server)
>> - (eglot--saved-initargs server)
>> - (eglot--language-ids server))
>> + (let* ((root (project-root (eglot--project server)))
>> + (project (project-current nil root)))
>> + (if (not project)
>> + (eglot--error "Project in `%s' is gone!" root)
>> + (eglot--connect (eglot--major-modes server)
>> + project
>> + (eieio-object-class-name server)
>> + (eglot--saved-initargs server)
>> + (eglot--language-ids server))))
>> (eglot--message "Reconnected!"))
>>
>> (defvar eglot--managed-mode) ; forward decl
>>
>>
>> Though it also raises a question about the caching strategy for VC-Aware
>> project backend. At the moment is associates a project with a directory
>> more or less indefinitely, and this is a case to watch out for.
>>
>> > Alternatively, maybe eglot--on-shutdown shouldn't automatically
>> > reconnect in the first place? Maybe reconnection should happen
>> > automatically only when some specific buffer tries to interact with the
>> > LSP - then it can run project-current in the context of that specific
>> > buffer, and see there's no project, and fail. Plus, if the user kills
>> > all the buffers in the project (possibly with project-kill-buffers)
>> > before deleting it, this approach would entirely avoid the unnecessary
>> > eglot reconnection attempt.
>>
>> This also sounds good, though it'd probably require more changes
>> overall. Additionally, perhaps I'd change the association from (server
>> -> project) to (server -> project-root), relying on the project
>> backends' internal caches to fetch the project value whenever it's
>> needed. That might be the most reliable approach. Perhaps the slowest in
>> theory, but hopefully not noticeably so.
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-05-19 15:08 ` Dmitry Gutov
@ 2024-11-21 19:46 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <ierplmotmxh.fsf@janestreet.com>
1 sibling, 0 replies; 12+ messages in thread
From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-21 19:46 UTC (permalink / raw)
To: Dmitry Gutov; +Cc: Eli Zaretskii, app-emacs-dev, João Távora, 70724
(Sending again after unarchiving the bug...)
Unfortunately the revised patch pushed by Joao is still broken for me,
because fetching project-name isn't guaranteed to work if the project
doesn't exist.
How about this instead?
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 092a9c6b9a5..502cb7bbb24 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1518,13 +1518,13 @@ eglot--connect
"Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
This docstring appeases checkdoc, that's all."
(let* ((default-directory (project-root project))
- (nickname (project-name project))
- (readable-name
+ (nickname
(progn
(unless (file-exists-p default-directory)
;; could happen because of bug#70724 or just because
- (eglot--error "Project '%s' is gone!" nickname))
- (format "EGLOT (%s/%s)" nickname managed-modes)))
+ (eglot--error "Project '%s' is gone!" default-directory))
+ (project-name project)))
+ (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
server-info
(contact (if (functionp contact) (funcall contact) contact))
(initargs
^ permalink raw reply related [flat|nested] 12+ messages in thread
[parent not found: <ierplmotmxh.fsf@janestreet.com>]
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
[not found] ` <ierplmotmxh.fsf@janestreet.com>
@ 2024-11-21 19:49 ` João Távora
2024-11-21 19:52 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 12+ messages in thread
From: João Távora @ 2024-11-21 19:49 UTC (permalink / raw)
To: Spencer Baugh; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
On Thu, Nov 21, 2024 at 7:19 PM Spencer Baugh <sbaugh@janestreet.com> wrote:
>
>
> Unfortunately the revised patch pushed by Joao is still broken for me,
> because fetching project-name isn't guaranteed to work if the project
> doesn't exist.
project was passed non-nil to eglot-connect, yes? A non-nil project
should still be able to identify itself even if its support in the filesystem
is missing, IMHO.
Anyway, this patch is slightly simpler (same idea)
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index e5c27de81fc..1e9a8a36343 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1518,13 +1518,11 @@ eglot--connect
"Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
This docstring appeases checkdoc, that's all."
(let* ((default-directory (project-root project))
- (nickname (project-name project))
- (readable-name
- (progn
- (unless (file-exists-p default-directory)
- ;; could happen because of bug#70724 or just because
- (eglot--error "Project '%s' is gone!" nickname))
- (format "EGLOT (%s/%s)" nickname managed-modes)))
+ (nickname (if (file-exists-p default-directory)
+ (project-name project)
+ ;; could happen because of bug#70724 or just because
+ (eglot--error "Project at `%s' is gone!"
default-directory)))
+ (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
server-info
(contact (if (functionp contact) (funcall contact) contact))
(initargs
>
> How about this instead?
>
> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
> index 092a9c6b9a5..502cb7bbb24 100644
> --- a/lisp/progmodes/eglot.el
> +++ b/lisp/progmodes/eglot.el
> @@ -1518,13 +1518,13 @@ eglot--connect
> "Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
> This docstring appeases checkdoc, that's all."
> (let* ((default-directory (project-root project))
> - (nickname (project-name project))
> - (readable-name
> + (nickname
> (progn
> (unless (file-exists-p default-directory)
> ;; could happen because of bug#70724 or just because
> - (eglot--error "Project '%s' is gone!" nickname))
> - (format "EGLOT (%s/%s)" nickname managed-modes)))
> + (eglot--error "Project '%s' is gone!" default-directory))
> + (project-name project)))
> + (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
> server-info
> (contact (if (functionp contact) (funcall contact) contact))
> (initargs
--
João Távora
^ permalink raw reply related [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-11-21 19:49 ` João Távora
@ 2024-11-21 19:52 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 19:55 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 12+ messages in thread
From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-21 19:52 UTC (permalink / raw)
To: João Távora; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
João Távora <joaotavora@gmail.com> writes:
> Anyway, this patch is slightly simpler (same idea)
>
> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
> index e5c27de81fc..1e9a8a36343 100644
> --- a/lisp/progmodes/eglot.el
> +++ b/lisp/progmodes/eglot.el
> @@ -1518,13 +1518,11 @@ eglot--connect
> "Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
> This docstring appeases checkdoc, that's all."
> (let* ((default-directory (project-root project))
> - (nickname (project-name project))
> - (readable-name
> - (progn
> - (unless (file-exists-p default-directory)
> - ;; could happen because of bug#70724 or just because
> - (eglot--error "Project '%s' is gone!" nickname))
> - (format "EGLOT (%s/%s)" nickname managed-modes)))
> + (nickname (if (file-exists-p default-directory)
> + (project-name project)
> + ;; could happen because of bug#70724 or just because
> + (eglot--error "Project at `%s' is gone!"
> default-directory)))
> + (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
> server-info
> (contact (if (functionp contact) (funcall contact) contact))
> (initargs
That looks good to me.
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-11-21 19:52 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-11-21 19:55 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 20:14 ` João Távora
0 siblings, 1 reply; 12+ messages in thread
From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-21 19:55 UTC (permalink / raw)
To: João Távora; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
Spencer Baugh <sbaugh@janestreet.com> writes:
> João Távora <joaotavora@gmail.com> writes:
>> Anyway, this patch is slightly simpler (same idea)
>>
>> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
>> index e5c27de81fc..1e9a8a36343 100644
>> --- a/lisp/progmodes/eglot.el
>> +++ b/lisp/progmodes/eglot.el
>> @@ -1518,13 +1518,11 @@ eglot--connect
>> "Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
>> This docstring appeases checkdoc, that's all."
>> (let* ((default-directory (project-root project))
>> - (nickname (project-name project))
>> - (readable-name
>> - (progn
>> - (unless (file-exists-p default-directory)
>> - ;; could happen because of bug#70724 or just because
>> - (eglot--error "Project '%s' is gone!" nickname))
>> - (format "EGLOT (%s/%s)" nickname managed-modes)))
>> + (nickname (if (file-exists-p default-directory)
>> + (project-name project)
>> + ;; could happen because of bug#70724 or just because
>> + (eglot--error "Project at `%s' is gone!"
>> default-directory)))
>> + (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
>> server-info
>> (contact (if (functionp contact) (funcall contact) contact))
>> (initargs
>
> That looks good to me.
Actually, wait, sorry, neither this nor your initial revised patch fixes
this bug at all. The process sentinel still errors because
eglot-reconnect errors. We need to actually not try to reconnect when
the project is gone.
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-11-21 19:55 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-11-21 20:14 ` João Távora
2024-11-21 20:51 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 12+ messages in thread
From: João Távora @ 2024-11-21 20:14 UTC (permalink / raw)
To: Spencer Baugh; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
Explain your scenario, please. And note that if you take the rug from
underneath Eglot it will error, period. That's by design. I'm not
willing to contort the code to do anything more than provide a
more or less understandable error message for such (relatively rare)
rug pulling. IOW sentinels erroring is part of Emacs life and not a
bug in itself, it's the error message that I'm willing to help ensure is
clear.
Please provide a backtrace and say if it's obtained with the very
same recipe in the beginning of the bug report.
João
On Thu, Nov 21, 2024 at 7:55 PM Spencer Baugh <sbaugh@janestreet.com> wrote:
>
> Spencer Baugh <sbaugh@janestreet.com> writes:
> > João Távora <joaotavora@gmail.com> writes:
> >> Anyway, this patch is slightly simpler (same idea)
> >>
> >> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
> >> index e5c27de81fc..1e9a8a36343 100644
> >> --- a/lisp/progmodes/eglot.el
> >> +++ b/lisp/progmodes/eglot.el
> >> @@ -1518,13 +1518,11 @@ eglot--connect
> >> "Connect to MANAGED-MODES, LANGUAGE-IDS, PROJECT, CLASS and CONTACT.
> >> This docstring appeases checkdoc, that's all."
> >> (let* ((default-directory (project-root project))
> >> - (nickname (project-name project))
> >> - (readable-name
> >> - (progn
> >> - (unless (file-exists-p default-directory)
> >> - ;; could happen because of bug#70724 or just because
> >> - (eglot--error "Project '%s' is gone!" nickname))
> >> - (format "EGLOT (%s/%s)" nickname managed-modes)))
> >> + (nickname (if (file-exists-p default-directory)
> >> + (project-name project)
> >> + ;; could happen because of bug#70724 or just because
> >> + (eglot--error "Project at `%s' is gone!"
> >> default-directory)))
> >> + (readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
> >> server-info
> >> (contact (if (functionp contact) (funcall contact) contact))
> >> (initargs
> >
> > That looks good to me.
>
> Actually, wait, sorry, neither this nor your initial revised patch fixes
> this bug at all. The process sentinel still errors because
> eglot-reconnect errors. We need to actually not try to reconnect when
> the project is gone.
--
João Távora
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-11-21 20:14 ` João Távora
@ 2024-11-21 20:51 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 23:36 ` João Távora
0 siblings, 1 reply; 12+ messages in thread
From: Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-11-21 20:51 UTC (permalink / raw)
To: João Távora; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
João Távora <joaotavora@gmail.com> writes:
> Explain your scenario, please. And note that if you take the rug from
> underneath Eglot it will error, period. That's by design. I'm not
> willing to contort the code to do anything more than provide a
> more or less understandable error message for such (relatively rare)
> rug pulling. IOW sentinels erroring is part of Emacs life and not a
> bug in itself, it's the error message that I'm willing to help ensure is
> clear.
I use (the equivalent of) git worktrees to have one repo checkout per
branch that I'm working on. As I finish work on a branch, I delete the
worktree with a shell command outside of Emacs. Thus I hit this error
several times a day, depending on how productive I am.
(The same workflow is used by ~everyone at my employer, and before we
can use Eglot widely, it would be ideal to get rid of this frequent
error)
> Please provide a backtrace and say if it's obtained with the very
> same recipe in the beginning of the bug report.
>
Sure, here's the backtrace with the patch in your last email. It is
obtained with the very same recipe in the beginning of the bug report: I
opened an (OCaml) file, did M-x eglot (starting ocaml-lsp), deleted the
directory, and it proceeded as I said in the beginning of the bug
report.
Debugger entered--Lisp error: (error "[eglot] Project at `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!")
signal(error ("[eglot] Project at `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!"))
error("[eglot] %s" "Project at `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!")
eglot--error("Project at `%s' is gone!" "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/")
(if (file-exists-p default-directory) (project-name project) (eglot--error "Project at `%s' is gone!" default-directory))
(let* ((default-directory (project-root project)) (nickname (if (file-exists-p default-directory) (project-name project) (eglot--error "Project at `%s' is gone!" default-directory))) (readable-name (format "EGLOT (%s/%s)" nickname managed-modes)) server-info (contact (if (functionp contact) (funcall contact) contact)) (initargs (cond ((keywordp (car contact)) contact) ((integerp (car (cdr contact))) (setq server-info (list (format "%s:%s" ... ...))) (list ':process #'(lambda nil ...))) ((and (stringp (car contact)) (cl-find-if #'... contact)) (setq server-info (list "<inferior process>")) (list ':process (jsonrpc-autoport-bootstrap readable-name contact :connect-args '...))) ((stringp (car contact)) (let* ((probe ...) (more-initargs ...) (contact ...)) (cons ':process (cons ... more-initargs)))))) (spread #'(lambda (fn) #'(lambda (server method params) (let ... ...)))) (server (apply #'make-instance class :name readable-name :events-buffer-config eglot-events-buffer-config :notification-dispatcher (funcall spread #'eglot-handle-notification) :request-dispatcher (funcall spread #'eglot-handle-request) :on-shutdown #'eglot--on-shutdown initargs)) (canceled nil) (tag (make-symbol "connected-catch-tag"))) (if server-info (progn (jsonrpc--debug server "Running language server: %s" (string-join server-info " ")))) (let* ((v server)) (\(setf\ eglot--saved-initargs\) initargs v)) (let* ((v server)) (\(setf\ eglot--project\) project v)) (let* ((v server)) (\(setf\ eglot--project-nickname\) nickname v)) (let* ((v server)) (\(setf\ eglot--languages\) (let* ((--cl-var-- managed-modes) (m nil) (--cl-var-- language-ids) (l nil) (--cl-var-- nil)) (while (and (consp --cl-var--) (progn (setq m ...) (consp --cl-var--))) (setq l (car --cl-var--)) (setq --cl-var-- (cons (cons m l) --cl-var--)) (setq --cl-var-- (cdr --cl-var--)) (setq --cl-var-- (cdr --cl-var--))) (nreverse --cl-var--)) v)) (run-hook-with-args 'eglot-server-initialized-hook server) (unwind-protect (condition-case _quit (let ((retval (catch tag (jsonrpc-async-request server :initialize ... :success-fn ... :timeout eglot-connect-timeout :error-fn ... :timeout-fn ...) (cond ... ...)))) (cond ((consp retval) (let* (...) (if ... ... ...))) ((null retval) (let nil (eglot--message "Waiting in background for server `%s'" ...) nil)) (t (let nil server)))) (quit (jsonrpc-shutdown server) (setq canceled 'quit))) (setq tag nil)))
eglot--connect((tuareg-mode) #s(jane-fe-project :workspace "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/" :vc (vc Hg "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/")) eglot-lsp-server (:process (closure ((contact "dispatch_ocaml_lsp.exe" "open! Core" "dev") (server-info "dispatch_ocaml_lsp.exe" "open! Core" "dev") (readable-name . "EGLOT (dune-add-disable-file-watcher-rpc/(tuareg-mode))") tramp-ssh-controlmaster-options tramp-use-ssh-controlmaster-options) nil (let ((default-directory default-directory) (tramp-use-ssh-controlmaster-options 'suppress) (tramp-ssh-controlmaster-options "-o ControlMaster=no -o ControlPath=none")) (make-process :name readable-name :command (setq server-info (eglot--cmd contact)) :connection-type 'pipe :coding 'utf-8-emacs-unix :noquery t :stderr (get-buffer-create (format "*%s stderr*" readable-name)) :file-handler t)))) ("tuareg"))
eglot-reconnect(#<eglot-lsp-server eglot-lsp-server-18f8056>)
(cond ((eglot--shutdown-requested server) t) ((not (eglot--inhibit-autoreconnect server)) (eglot--warn "Reconnecting after unexpected server exit.") (eglot-reconnect server)) ((timerp (eglot--inhibit-autoreconnect server)) (eglot--warn "Not auto-reconnecting, last one didn't last long.")))
eglot--on-shutdown(#<eglot-lsp-server eglot-lsp-server-18f8056>)
funcall(eglot--on-shutdown #<eglot-lsp-server eglot-lsp-server-18f8056>)
(unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn _timer) (funcall error-fn '(:code -1 :message "Server died"))) jsonrpc-lambda-elem168)) (jsonrpc--continuations connection)) (jsonrpc--message "Server exited with status %s" (process-exit-status proc)) (delete-process proc) (let* ((p (and t (slot-value connection '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall (jsonrpc--on-shutdown connection) connection))
(progn (save-current-buffer (set-buffer (jsonrpc-events-buffer connection)) (let ((inhibit-read-only t)) (insert "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn _error-fn timer) (if timer (progn (cancel-timer timer)))) jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919 (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923 (cdr-safe x921))) (progn (ignore (null x923)) (let ((timer x920)) (if timer (progn (cancel-timer timer)))))))))))) (jsonrpc--deferred-actions connection)) (process-put proc 'jsonrpc-sentinel-cleanup-started t) (unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn _timer) (funcall error-fn '(:code -1 :message "Server died"))) jsonrpc-lambda-elem168)) (jsonrpc--continuations connection)) (jsonrpc--message "Server exited with status %s" (process-exit-status proc)) (delete-process proc) (let* ((p (and t (slot-value connection '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall (jsonrpc--on-shutdown connection) connection)))
(if (not (process-live-p proc)) (progn (save-current-buffer (set-buffer (jsonrpc-events-buffer connection)) (let ((inhibit-read-only t)) (insert "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn _error-fn timer) (if timer (progn (cancel-timer timer)))) jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919 (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923 (cdr-safe x921))) (progn (ignore (null x923)) (let ((timer x920)) (if timer (progn ...))))))))))) (jsonrpc--deferred-actions connection)) (process-put proc 'jsonrpc-sentinel-cleanup-started t) (unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn _timer) (funcall error-fn '(:code -1 :message "Server died"))) jsonrpc-lambda-elem168)) (jsonrpc--continuations connection)) (jsonrpc--message "Server exited with status %s" (process-exit-status proc)) (delete-process proc) (let* ((p (and t (slot-value connection '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall (jsonrpc--on-shutdown connection) connection))))
(let ((connection (process-get proc 'jsonrpc-connection))) (jsonrpc--debug connection "Connection state change: `%s'" change) (if (not (process-live-p proc)) (progn (save-current-buffer (set-buffer (jsonrpc-events-buffer connection)) (let ((inhibit-read-only t)) (insert "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn _error-fn timer) (if timer (progn (cancel-timer timer)))) jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919 (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923 (cdr-safe x921))) (progn (ignore (null x923)) (let (...) (if timer ...)))))))))) (jsonrpc--deferred-actions connection)) (process-put proc 'jsonrpc-sentinel-cleanup-started t) (unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn _timer) (funcall error-fn '(:code -1 :message "Server died"))) jsonrpc-lambda-elem168)) (jsonrpc--continuations connection)) (jsonrpc--message "Server exited with status %s" (process-exit-status proc)) (delete-process proc) (let* ((p (and t (slot-value connection '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall (jsonrpc--on-shutdown connection) connection)))))
jsonrpc--process-sentinel(#<process EGLOT (dune-add-disable-file-watcher-rpc/(tuareg-mode))> "exited abnormally with code 1\n")
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-11-21 20:51 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-11-21 23:36 ` João Távora
0 siblings, 0 replies; 12+ messages in thread
From: João Távora @ 2024-11-21 23:36 UTC (permalink / raw)
To: Spencer Baugh; +Cc: Dmitry Gutov, Eli Zaretskii, app-emacs-dev, 70724
[-- Attachment #1: Type: text/plain, Size: 11722 bytes --]
So, the error is explanatory, no?? As far as I can tell your original
patch also signalled an error, and that error happened in the sentinel.
If you want to avoid this error and silently proceed, for the benefit
of your particular workflow, write a project backend that keeps its
vital information despite having lost its file system backing.
Or, maybe better, write some advice to eglot-autoreconnect which
is an external function (and thus offers some stability guarantee of
its interface). eglot-reconnect takes the server as argument and
you can query the project to know if its still valid or not and noop
in the case it's been deleted from the filesystem. But this is too
specific to generalize in Eglot. I for one like to be warned of these
error, because for me having a connected-to project suddenly
deleted in an exception, it's not the rule.
João
On Thu, Nov 21, 2024, 20:51 Spencer Baugh <sbaugh@janestreet.com> wrote:
> João Távora <joaotavora@gmail.com> writes:
>
> > Explain your scenario, please. And note that if you take the rug from
> > underneath Eglot it will error, period. That's by design. I'm not
> > willing to contort the code to do anything more than provide a
> > more or less understandable error message for such (relatively rare)
> > rug pulling. IOW sentinels erroring is part of Emacs life and not a
> > bug in itself, it's the error message that I'm willing to help ensure is
> > clear.
>
> I use (the equivalent of) git worktrees to have one repo checkout per
> branch that I'm working on. As I finish work on a branch, I delete the
> worktree with a shell command outside of Emacs. Thus I hit this error
> several times a day, depending on how productive I am.
>
> (The same workflow is used by ~everyone at my employer, and before we
> can use Eglot widely, it would be ideal to get rid of this frequent
> error)
>
> > Please provide a backtrace and say if it's obtained with the very
> > same recipe in the beginning of the bug report.
> >
>
> Sure, here's the backtrace with the patch in your last email. It is
> obtained with the very same recipe in the beginning of the bug report: I
> opened an (OCaml) file, did M-x eglot (starting ocaml-lsp), deleted the
> directory, and it proceeded as I said in the beginning of the bug
> report.
>
> Debugger entered--Lisp error: (error "[eglot] Project at
> `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!")
> signal(error ("[eglot] Project at
> `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!"))
> error("[eglot] %s" "Project at
> `/usr/local/home/sbaugh/workspaces/fe-880764/+share+/' is gone!")
> eglot--error("Project at `%s' is gone!"
> "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/")
> (if (file-exists-p default-directory) (project-name project)
> (eglot--error "Project at `%s' is gone!" default-directory))
> (let* ((default-directory (project-root project)) (nickname (if
> (file-exists-p default-directory) (project-name project) (eglot--error
> "Project at `%s' is gone!" default-directory))) (readable-name (format
> "EGLOT (%s/%s)" nickname managed-modes)) server-info (contact (if
> (functionp contact) (funcall contact) contact)) (initargs (cond ((keywordp
> (car contact)) contact) ((integerp (car (cdr contact))) (setq server-info
> (list (format "%s:%s" ... ...))) (list ':process #'(lambda nil ...))) ((and
> (stringp (car contact)) (cl-find-if #'... contact)) (setq server-info (list
> "<inferior process>")) (list ':process (jsonrpc-autoport-bootstrap
> readable-name contact :connect-args '...))) ((stringp (car contact)) (let*
> ((probe ...) (more-initargs ...) (contact ...)) (cons ':process (cons ...
> more-initargs)))))) (spread #'(lambda (fn) #'(lambda (server method params)
> (let ... ...)))) (server (apply #'make-instance class :name readable-name
> :events-buffer-config eglot-events-buffer-config :notification-dispatcher
> (funcall spread #'eglot-handle-notification) :request-dispatcher (funcall
> spread #'eglot-handle-request) :on-shutdown #'eglot--on-shutdown initargs))
> (canceled nil) (tag (make-symbol "connected-catch-tag"))) (if server-info
> (progn (jsonrpc--debug server "Running language server: %s" (string-join
> server-info " ")))) (let* ((v server)) (\(setf\ eglot--saved-initargs\)
> initargs v)) (let* ((v server)) (\(setf\ eglot--project\) project v)) (let*
> ((v server)) (\(setf\ eglot--project-nickname\) nickname v)) (let* ((v
> server)) (\(setf\ eglot--languages\) (let* ((--cl-var-- managed-modes) (m
> nil) (--cl-var-- language-ids) (l nil) (--cl-var-- nil)) (while (and (consp
> --cl-var--) (progn (setq m ...) (consp --cl-var--))) (setq l (car
> --cl-var--)) (setq --cl-var-- (cons (cons m l) --cl-var--)) (setq
> --cl-var-- (cdr --cl-var--)) (setq --cl-var-- (cdr --cl-var--))) (nreverse
> --cl-var--)) v)) (run-hook-with-args 'eglot-server-initialized-hook server)
> (unwind-protect (condition-case _quit (let ((retval (catch tag
> (jsonrpc-async-request server :initialize ... :success-fn ... :timeout
> eglot-connect-timeout :error-fn ... :timeout-fn ...) (cond ... ...))))
> (cond ((consp retval) (let* (...) (if ... ... ...))) ((null retval) (let
> nil (eglot--message "Waiting in background for server `%s'" ...) nil)) (t
> (let nil server)))) (quit (jsonrpc-shutdown server) (setq canceled 'quit)))
> (setq tag nil)))
> eglot--connect((tuareg-mode) #s(jane-fe-project :workspace
> "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/" :vc (vc Hg
> "/usr/local/home/sbaugh/workspaces/fe-880764/+share+/")) eglot-lsp-server
> (:process (closure ((contact "dispatch_ocaml_lsp.exe" "open! Core" "dev")
> (server-info "dispatch_ocaml_lsp.exe" "open! Core" "dev") (readable-name .
> "EGLOT (dune-add-disable-file-watcher-rpc/(tuareg-mode))")
> tramp-ssh-controlmaster-options tramp-use-ssh-controlmaster-options) nil
> (let ((default-directory default-directory)
> (tramp-use-ssh-controlmaster-options 'suppress)
> (tramp-ssh-controlmaster-options "-o ControlMaster=no -o
> ControlPath=none")) (make-process :name readable-name :command (setq
> server-info (eglot--cmd contact)) :connection-type 'pipe :coding
> 'utf-8-emacs-unix :noquery t :stderr (get-buffer-create (format "*%s
> stderr*" readable-name)) :file-handler t)))) ("tuareg"))
> eglot-reconnect(#<eglot-lsp-server eglot-lsp-server-18f8056>)
> (cond ((eglot--shutdown-requested server) t) ((not
> (eglot--inhibit-autoreconnect server)) (eglot--warn "Reconnecting after
> unexpected server exit.") (eglot-reconnect server)) ((timerp
> (eglot--inhibit-autoreconnect server)) (eglot--warn "Not auto-reconnecting,
> last one didn't last long.")))
> eglot--on-shutdown(#<eglot-lsp-server eglot-lsp-server-18f8056>)
> funcall(eglot--on-shutdown #<eglot-lsp-server eglot-lsp-server-18f8056>)
> (unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply
> #'(lambda (_id _method _success-fn error-fn _timer) (funcall error-fn
> '(:code -1 :message "Server died"))) jsonrpc-lambda-elem168))
> (jsonrpc--continuations connection)) (jsonrpc--message "Server exited with
> status %s" (process-exit-status proc)) (delete-process proc) (let* ((p (and
> t (slot-value connection '-autoport-inferior)))) (if p (delete-process p)
> nil)) (funcall (jsonrpc--on-shutdown connection) connection))
> (progn (save-current-buffer (set-buffer (jsonrpc-events-buffer
> connection)) (let ((inhibit-read-only t)) (insert
> "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda
> (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn
> _error-fn timer) (if timer (progn (cancel-timer timer))))
> jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash
> #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919
> (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe
> x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923
> (cdr-safe x921))) (progn (ignore (null x923)) (let ((timer x920)) (if timer
> (progn (cancel-timer timer)))))))))))) (jsonrpc--deferred-actions
> connection)) (process-put proc 'jsonrpc-sentinel-cleanup-started t)
> (unwind-protect (mapc #'(lambda (jsonrpc-lambda-elem168) (apply #'(lambda
> (_id _method _success-fn error-fn _timer) (funcall error-fn '(:code -1
> :message "Server died"))) jsonrpc-lambda-elem168)) (jsonrpc--continuations
> connection)) (jsonrpc--message "Server exited with status %s"
> (process-exit-status proc)) (delete-process proc) (let* ((p (and t
> (slot-value connection '-autoport-inferior)))) (if p (delete-process p)
> nil)) (funcall (jsonrpc--on-shutdown connection) connection)))
> (if (not (process-live-p proc)) (progn (save-current-buffer (set-buffer
> (jsonrpc-events-buffer connection)) (let ((inhibit-read-only t)) (insert
> "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda
> (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn
> _error-fn timer) (if timer (progn (cancel-timer timer))))
> jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash
> #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919
> (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe
> x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923
> (cdr-safe x921))) (progn (ignore (null x923)) (let ((timer x920)) (if timer
> (progn ...))))))))))) (jsonrpc--deferred-actions connection)) (process-put
> proc 'jsonrpc-sentinel-cleanup-started t) (unwind-protect (mapc #'(lambda
> (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn
> _timer) (funcall error-fn '(:code -1 :message "Server died")))
> jsonrpc-lambda-elem168)) (jsonrpc--continuations connection))
> (jsonrpc--message "Server exited with status %s" (process-exit-status
> proc)) (delete-process proc) (let* ((p (and t (slot-value connection
> '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall
> (jsonrpc--on-shutdown connection) connection))))
> (let ((connection (process-get proc 'jsonrpc-connection)))
> (jsonrpc--debug connection "Connection state change: `%s'" change) (if (not
> (process-live-p proc)) (progn (save-current-buffer (set-buffer
> (jsonrpc-events-buffer connection)) (let ((inhibit-read-only t)) (insert
> "\n----------b---y---e---b---y---e----------\n"))) (mapc #'(lambda
> (jsonrpc-lambda-elem167) (apply #'(lambda (_id _method _success-fn
> _error-fn timer) (if timer (progn (cancel-timer timer))))
> jsonrpc-lambda-elem167)) (jsonrpc--continuations connection)) (maphash
> #'(lambda (_ triplet) (progn (ignore (consp triplet)) (let* ((x919
> (cdr-safe triplet))) (progn (ignore (consp x919)) (let* ((x920 (car-safe
> x919)) (x921 (cdr-safe x919))) (progn (ignore (consp x921)) (let* ((x923
> (cdr-safe x921))) (progn (ignore (null x923)) (let (...) (if timer
> ...)))))))))) (jsonrpc--deferred-actions connection)) (process-put proc
> 'jsonrpc-sentinel-cleanup-started t) (unwind-protect (mapc #'(lambda
> (jsonrpc-lambda-elem168) (apply #'(lambda (_id _method _success-fn error-fn
> _timer) (funcall error-fn '(:code -1 :message "Server died")))
> jsonrpc-lambda-elem168)) (jsonrpc--continuations connection))
> (jsonrpc--message "Server exited with status %s" (process-exit-status
> proc)) (delete-process proc) (let* ((p (and t (slot-value connection
> '-autoport-inferior)))) (if p (delete-process p) nil)) (funcall
> (jsonrpc--on-shutdown connection) connection)))))
> jsonrpc--process-sentinel(#<process EGLOT
> (dune-add-disable-file-watcher-rpc/(tuareg-mode))> "exited abnormally with
> code 1\n")
>
[-- Attachment #2: Type: text/html, Size: 12880 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted
2024-05-04 1:09 ` Dmitry Gutov
2024-05-18 8:31 ` Eli Zaretskii
@ 2024-06-06 20:36 ` Dmitry Gutov
1 sibling, 0 replies; 12+ messages in thread
From: Dmitry Gutov @ 2024-06-06 20:36 UTC (permalink / raw)
To: Spencer Baugh, 70724-done; +Cc: app-emacs-dev, João Távora
On 04/05/2024 04:09, Dmitry Gutov wrote:
>
> I think I like this solution (as long as the nil value returned by
> project-current on this step is appropriately handled).
>
> Something like:
>
> diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
> index 6896baf30ce..7b2461c3ce6 100644
> --- a/lisp/progmodes/eglot.el
> +++ b/lisp/progmodes/eglot.el
> @@ -1426,11 +1426,15 @@ eglot-reconnect
> (interactive (list (eglot--current-server-or-lose) t))
> (when (jsonrpc-running-p server)
> (ignore-errors (eglot-shutdown server interactive nil
> 'preserve-buffers)))
> - (eglot--connect (eglot--major-modes server)
> - (eglot--project server)
> - (eieio-object-class-name server)
> - (eglot--saved-initargs server)
> - (eglot--language-ids server))
> + (let* ((root (project-root (eglot--project server)))
> + (project (project-current nil root)))
> + (if (not project)
> + (eglot--error "Project in `%s' is gone!" root)
> + (eglot--connect (eglot--major-modes server)
> + project
> + (eieio-object-class-name server)
> + (eglot--saved-initargs server)
> + (eglot--language-ids server))))
> (eglot--message "Reconnected!"))
>
> (defvar eglot--managed-mode) ; forward decl
Okay, I've pushed a slightly revised version of this patch now. It makes
sense to me, even if some caching issues might remain in project backend(s).
Spencer, please see if it takes care of your scenario.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-11-21 23:36 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-02 19:37 bug#70724: 29.2.50; eglot-reconnect errors when the project is deleted Spencer Baugh
2024-05-04 1:09 ` Dmitry Gutov
2024-05-18 8:31 ` Eli Zaretskii
2024-05-19 15:08 ` Dmitry Gutov
2024-11-21 19:46 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
[not found] ` <ierplmotmxh.fsf@janestreet.com>
2024-11-21 19:49 ` João Távora
2024-11-21 19:52 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 19:55 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 20:14 ` João Távora
2024-11-21 20:51 ` Spencer Baugh via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-21 23:36 ` João Távora
2024-06-06 20:36 ` Dmitry Gutov
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).