emacs-ess / ESS

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

How to interrupt a job in the inferior process from the ESS buffer? #939

Open prosoitos opened 5 years ago

prosoitos commented 5 years ago

From the iESS buffer, an R job can be interrupted by running C-c C-c or comint-interrupt-subjob.

But how can this be achieved from the ESS buffer?

I usually send commands to the iESS buffer from the ESS buffer with ess-eval-paragraph-and-step and the like. So my active buffer is the ESS buffer. If I accidentally send a terrible command that will make R go crazy, I can't stop it because Emacs gets overwhelmed by the very demanding running process and I cannot switch to the iESS buffer to then stop it with C-c C-c. Everything beside the running process is frozen and I have the option to let it run for ages (if it ever finishes) or killing Emacs altogether.

What is the proper way to handle this?

Thanks! and sorry this is probably not an issue as there must be a way to handle this properly already. I can ask in StackOverflow or Emacs StackExchange if it is inappropriate to open an issue for this. I did search through the manual though and could not find anything beside comint-interrupt-subjob (which doesn't work in the situation I described).

jabranham commented 5 years ago

There's not a built-in function for that. It would be easy to make, but if the R process is hanging your entire Emacs session, it will be pretty useless.

You can always just pkill R to kill the R process, which should restore Emacs back to normal. You'll lose whatever R was doing, of course.

prosoitos commented 5 years ago

Ah, damn.

I use EXWM (Emacs X Window Manager), so when Emacs hangs, everything hangs... I can switch to another tty and sometimes, pkill R works. But sometimes it makes Emacs crash.

but if the R process is hanging your entire Emacs session, it will be pretty useless.

Are you sure? when I send a terrible command from within iESS, I kill it with C-c C-c before it runs for too long and gets out of hand. But for some reason, switching windows seems harder and I can never catch it in time from within the ESS buffer.

prosoitos commented 5 years ago

I feel that it might not work some of the time, but it might still work some times. So it might be worth having a function to try in case sending it early enough prevents everything to hang.

But I could be wrong of course :stuck_out_tongue: and maybe it would never work.

prosoitos commented 5 years ago

I wish there were a way to prevent the iESS process to ever getting out of hand and taking so much overall resource to make the rest of Emacs hang until it is done. That would then ensure that there is always a way to interrupt it from within Emacs (which allows not to have to kill R, which is nice, and in the case of using EXWM and having everything relies on Emacs, it is really key).

But some resource allocation safety limit is probably way beyond the ESS package and might be something to implement deeper in Emacs, or maybe even at the whole system level?

farcego commented 5 years ago

Not sure if I follow the issue properly, but I suffer of the same issue from time to time. So, when I send an awful paragraph from the script to iESS that "frozen" everything I press C-g and then I can switch to iESS buffer and use C-c C-c. Maybe is C-g what you are after? Quitting I think this is more an emacs issue than an ESS issue though.

prosoitos commented 5 years ago

C-g does not help in my case.

nverno commented 5 years ago

If you realize fast enough you could try to interrupt / quit the process with ess-interrupt, ess-quit, or others in ess-inf.el.

prosoitos commented 5 years ago

Ah, great! I didn't know about these functions. I will map them to some keybindings and experiment with them. Thank you for the suggestion!

ess-interrupt looks like it might be what I was hoping for.

vspinu commented 5 years ago

@prosoitos what is the cause of the hang more concretely? Very long lines (strings?)? From what you describe this seems to be the case. It's the re-display which hangs emacs and it's notoriously hard to deal with. Emacs is pretty bad with long lines.

On ESS we could deal with this and quite easily actually (I think). [oppened #941]. Will have a look when I have time.

Regarding the interrupts from the script buffer, it could be handy indeed. I used it all the time in CIDER where it is bound to C-c C-b, a key which we cannot used.

prosoitos commented 5 years ago

By long lines, do you mean very long outputs? If so, yes: for instance, I can make it happen by calling str(obj) if obj is a list of many very large lists (like a spacial object for instance). Or when I accidentally output some very large data frame or other object containing many values.

When such output is very long, after a number of screen-full of it, Emacs starts to hang. I'd like to be able to simply stop it. Sometimes I do want to output something large (as with str()), but most of the time, those are accidents.

But I am not sure it is what you meant though.

Regarding the interrupts from the script buffer, it could be handy indeed. I used it all the time in CIDER where it is bound to C-c C-b, a key which we cannot used.

I would be happy to have such a function. I don't care what the default key binding would be as I would probably rebind it anyway :smile:

prosoitos commented 5 years ago

Looking at the issue you opened, maybe my solution is to set options(max.print = *) in R... I didn't know this option existed...

jabranham commented 5 years ago

Here's some suggestions for keybinginds for ess-interrupt, WDYT?

or we could rebind C-c C-p away from its current ess-eval-paragraph-and-step and make it into a process-controlling keymap so that e.g. C-c C-p C-q would issue ess-quit and C-c C-p C-i would issue ess-interrupt. There might be other process-controlling commands we put there; I haven't thought about it too much.

prosoitos commented 5 years ago

I know what I'll do on my end, but I am sure that it won't please you for the default keybinding as it would affect users and their habits...

On my end, I will bind it to C-c C-c so that this will become my binding to interrupt the process, whether I am in the ESS buffer or in the iESS buffer (and I will rebind ess-eval-region-or-function-or-paragraph-and-step to something else. In truth, I already have as C-c C-c is not all that convenient to run multiple times in a row).

Not having to think in which buffer I am, and thus which binding I should use, but run the same binding automatically, will save time to interrupt things quickly and time can be critical in some cases, depending on what command got sent to the process. But again, I suspect that you don't want to change bindings that have been there for a while :slightly_smiling_face: (though, you were considering remapping ess-eval-paragraph-and-step...).

vspinu commented 5 years ago

C-c C-w: close to C-c C-q on QWERTY keyboards, which is ess-quit bound to project map.

C-c C-/: easy to type on a lot of keyboards

can be but is fairly inconvenient to type

or we could rebind C-c C-p away from its current ess-eval-paragraph-and-step

It's a job for sesman-map. Probably C-c C-s i (and C-c C-s C-i) as per the mnemonic argument.