emacs-ess / ESS

Emacs Speaks Statistics: ESS
https://ess.r-project.org/
GNU General Public License v3.0
613 stars 160 forks source link

How can I salvage a bad start? -- i.e, when no "ESSR" in `search()` #1220

Closed mmaechler closed 1 year ago

mmaechler commented 1 year ago

This currently happens quite regularly to me, notably when R is started after I work with an *.R file in emacs (and ESS is loaded of course). It also happens when I run R in the (C-level) debugger, i.e., after C-u M-x R (because in the *R* buffer, there's the gdb> prompt, and I first have to type r (for run) there to start R and all this takes little while.

Anyway back to the question: Notably when R runs from R -d gdb it's a pain when "ESSR" is missing because practically everything interactive fails (such as TAB completion for R function names).

What M-x .... (or other way) can I use to "restart" that second part of M-x R ?
{{yes, I think I could find out myself; but it's something we should be aware of that users eventually want to be able to do}}

vspinu commented 1 year ago

There is ess-r-initialize-on-start function which does the initialization including loading ESSR. Also ess-r-load-ESSR which only loads ESSR. I have just made them both interactive so you can do M-x ess-r-initialize-on-start.

Would be good to know why ESSR is not loaded for you though. Maybe some timeout?

lionel- commented 1 year ago

Hi Martin,

I saw that you made this comment in #1243:

But in the case you mention, I occasionally observe even much worse: the whole ESSR functionality is then not part of the search() path

Is this with remotes or locally? Can you reproduce fairly consistently? What if you remove all the eval-linewise commands that you have in your post-run-hook, does it make a difference?

ESS has been very stable on my end ever since you fixed #1198. I'd like to solve the remaining issues (that are not related to polymode) that prevent you from using ESS reliably.

Note: Regarding R -d gdb, I think we might need a specialised mode to effectively deal with it. Or maybe we should detect the R opening words before sending any R input (and ESSR load commands). In any case this particular case seems out of scope, especially when it's so easy to debug from outside. (And often more effective, I do all my debugging in vscode nowadays, with R running in Emacs.)

lionel- commented 1 year ago

I've pushed some changes to make R -d gdb work again, and added a unit test for it. I don't have gdb but I tested with lldb. Can you please let me know if those changes improved ESSR initialisation @mmaechler?

mmaechler commented 1 year ago

TLDR: It "works" if I 1) use C-g after a first freeze 2) know to use M-x ess-r-initialize-r-on-start manually after having started R inside gdb.

Yes, in some sense R -d gdb does work again. .. (but most users would not find out how but give up probably): For me, Emacs gets still stuck after displaying the
R starting directory? prompt in the minibuffer. I can C-g that and the see the *R* buffer with its (gdb) prompt. {ESS still having wrongly sent my "screen options" options(width=81, length=99999) in to the *R* buffer even before gdb prints its banner/header

GNU gdb (GDB) Fedora 12.1-2.fc36
Copyright (C) 2022 Free Software Foundation, Inc.
...................

but of course I can live with that (the screen options for R being sent too early) and always had to. The problem is that when I later type r (for run) into the *R* buffer -- which is still in gdb's prompt -- R starts fine, but Emacs/ESS of course had been interrupted (by my C-g way above, I assume) so that when R now runs ("inside gdb"), and I check "ESSR" %in% search() I get the dreaded FALSE . Now -- after looking it up in this github thread :-) -- I can use interactive M-x ess-r-load-ESSR and things seem fine.. well not really: E.g C-c C-v ("help in R") behaves normally at first, e.g. tab-completion on names on which I could get help, but then when I do choose, say lm as the one to get help about, it hangs, it seems only the kill signal stops it.

So trying again, this times the "complete" M-x ess-r-initialize-on-start .. it quickly errors (recovered from *Messages*):

user-error: ESS process not ready. Finish your command before trying again

but it actually has worked, i.e., "ESSR" %in% search() is TRUE now and also, e.g. R help via C-c C-v works. I think if that user-error could be prevented, we'd be somewhat close to good. Even quite a bit nicer would be if ESS at this point would mention something like

  To enable ESS, do use    M-x ess-r-initialize-on-start    after starting R 

to help users find the solution once they are at this stage.

lionel- commented 1 year ago

ESS still having wrongly sent my "screen options" options(width=81, length=99999) in to the R buffer even before gdb prints its banner/header

While working on #1243 I discovered that the generic post-run hook is run too early, before ESSR had a chance to start. In the debugger case this hook runs early for another reason, we haven't had a chance to send "run" yet to gdb/lldb.

Try moving your R config to the mode-specific ess-r-post-run-hook. You need to be careful about the ordering of those commands as I've documented in https://github.com/emacs-ess/ESS/commit/536b5b914a75afa37ee05aa8ba0aecd0f9c9eb33. Also you should be able to remove the screen options from your config since it's now run by default (in the background).

If you update to the latest dev ESS and fix your post-run-hook config, do you see any improvements? If not could you send me an ess-verbose log please?

Regarding salvaging bad starts, we could probably detect early exits during ess-r-initialize-on-start with an unwind-protect clause. Then we could disable background commands (but currently we can only do it within a buffer or throughout Emacs, we also need a way to disable them by process which would make more sense here) and let the user know something went wrong and how to fix it.

mmaechler commented 1 year ago

Wow! Indeed, I actually had added the ess screen-options to both hooks. I now removed it from the ess-post-run-hook i.e. do not add anything there. .. but this (and more, as previously) to ess-r-post-run-hook. This seems to change the picture completely for me: Now even C-u M-x R with subsequent -d gdb works smoothly ... I don't have to do any hacks (the above 1. and 2.) any more, and indeed ESS starts R successfully, i.e., with subsequent "ESSR" in search() and also my R calls, including the screen options are executed at the correct time (after R has started inside gdb and got a prompt ..).

This is a really a big step forward ! -- thank you Lionel!

lionel- commented 1 year ago

I've added the early exit detection in: https://github.com/emacs-ess/ESS/commit/6305791d44cdeb5319c5ccdb1ad0ad4ac6405010

So now at least when you do C-g you will get an error with instructions about using ess-r-initialize (I've renamed it, it was originally ess-r-initialize-on-start which is a bit redundant). This still doesn't detect when an early exit happens on the R side, I've added a TODO note about that.

While I was in there I cleanup up the options command a bit: https://github.com/emacs-ess/ESS/commit/27e5af801aa04c200905ce62cff14f0e5b6ab187. We no longer rely on S config and I've removed some abstractions that didn't seem needed so that it's more explicit what we are setting exactly, it's now all in one place.

lionel- commented 1 year ago

oh I forgot to mention I added a startup timeout of 5 seconds, configurable via ess-r--init-timeout. This could be increased or removed if that causes issues with remotes. I thought that 5 seconds is a really long time for Emacs to be blocked so it made sense to timeout (and thus trigger the error about startup failure and how to recover).

lionel- commented 1 year ago

Regarding salvaging bad starts, we could probably detect early exits during ess-r-initialize-on-start with an unwind-protect clause. Then we could disable background commands (but currently we can only do it within a buffer or throughout Emacs, we also need a way to disable them by process which would make more sense here) and let the user know something went wrong and how to fix it.

We now disable background commands locally in #1244, in addition to failing with an informative error.

lionel- commented 1 year ago

With https://github.com/emacs-ess/ESS/commit/47f86dbe093f84358ffc0bc875e10a65d2556368 we now propagate errors during background commands to the elisp side, including errors during initialization of ESSR. When init fails on the R side, the new error handling will now take over (inform the user about how to recover and disable background commands until then).

lionel- commented 1 year ago

With https://github.com/emacs-ess/ESS/commit/71b0e364a1e8fe37e56c7783fd35c54c233e8137, ESS now asks users if they want to disable background commands for the current process when a user quit with C-g is detected during a background eval. I'm hoping this will allow users to easily make ESS usable again when there is something wrong that causes errors or hangs.

By the way @mmaechler I've discovered you can do this to get a backtrace on C-g.

(setq debug-on-quit t)