How to interrupt process in Rstudio elegantly? - r

Maybe it's because I'm too careless and often write the wrong code when dealing with big data. I tried to click the stop button(the red one in Rstudio), ctrl + c, ctrl+z, none of them can interrupt the process, and in the end I have to terminate the ```rsession`` and Rstudio in the terminal. Is ther anything else I can do? (I am using dplyr)

You can press esc and wait the until job is cancelled

Related

emacs ess-indent-or-complete sends newline to R process

Occasionally, for reasons I can not determine, ess-indent-or-complete sends an input to the R console. In other words, I will be typing something, hit tab to autocomplete (or company autocompletes for me), and the R process will update with a newline (.R file on the left "buffer", R process on the right):
x <- mea█ | >
|
|
... and then I hit tab to complete "mean":
x <- mean█ | >
| > ## note the new line here
|
This can be really annoying for at least two reasons:
It fills up the process buffer with blank lines.
If I am using a browser(), it advances lines which is often undesirable.
I have tried to diagnose this myself to no avail. Restarting emacs fixes it every time, however it seems to start happening at random throughout the day. Once it starts it does not stop until emacs restarts.
I am running emacs 27.1, ess-20210818.843 (though this has been a thing for a long time, so I don't believe it is version-specific), and am in ESS[R] mode.
Calling M-: (ess-command "") from my .R file buffer replicates the undesired behavior once it starts happening in a particular session. I have no insight beyond this.
I think you solved it yourself, with your GH issue suggestion:
https://github.com/emacs-ess/ESS/issues/1198
I've changed things in my own version of ESS, and will commit after a few days of testing it.
Thank you VERY VERY much for persevering and (I think) finding the fault .. a simple typo inside the internal (ess--command-make-restore-function)

Can we pause the debugging process in R?

I wrote code which has been running for more than 12 hours and I run it by mtrace() and go() function (from the debug package). Now I want to pause this and go through the remaining process myself by pressing enter, is there a way to do that?
mtrace(main)
F<-main()
go()

Tweaking the R readline behavior

The R interactive interface implements the shell-like read line behavior (I have no better words to formulate this...).
For example, pressing Ctrl-W kills the preceding word.
Now, I would like this mechanism to stop at characters other than alphanumeric. For example, if I have entered
data.frame(Ant
and press Ctrl-W, the whole string data.frame(Ant is killed. I would much prefer the Ctrl-W to kill the Ant and stop short of the left parenthesis.
Is there a way of tweaking this behavior?
The behaviour of readline depends upon the operating system and the IDE. On Windows, CRTL-W doesn't delete the previous word. I don't think that there's a trivial way of changing the behaviour. At a guess, start digging around in:
http://svn.r-project.org/R/trunk/src/library/utils/src/io.c

What exactly does the stop button in R do?

Does the stop button (or esc key) in R stop a loop after a completion?
e.g.:
x=1:100
i=2
repeat{
x[i]=x[i]+3
x[i-1]=x[i]+1
i=i+1
if(i>100){break}
}
and I hit stop before the loop ends... will the loop break at the end of a repeat, or will it break in the middle?
Does anyone know where to find documentation on this stop button?
Thanks
The "stop button" is actually a GUI feature so its documentation should be consulted. The keyboard ctrl-C or 'esc-key' should do the same. The commentary I have seen is rather non-committal about how soon an interrupt will be handled. It says something like: "well written code will handle interrupts promptly."
> x=1:1000000
> i=2
> repeat{
+ x[i]=x[i]+3
+ x[i-1]=x[i]+1
+ i=i+1
+ if(i>length(x)){break} } # esc key hit promptly
> i
[1] 15128
You should read the help page for:
?conditions
The 'R for Mac OS X FAQ' says: "However, if the executed code does not check for interrupts (using `R_CheckUserInterrupt') there may be no way of stopping R. In that case it may be worth alerting the maintainer of the package to allow interruption (if appropriate)."
This search will let you page through postings to R-devel that mention that internal mechanism by name: http://markmail.org/search/?q=list%3Aorg.r-project+R_CheckUserInterrupt

How to successfully interrupt R from tcltk scripting widget?

I am trying to create a scripting widget for R using the tcltk package. But I don't know how to to create a STOP button to interrupt a script coming from the widget. Basically, I would like to have a button, a menu option, and/or a key binding that will interrupt the current script execution, but I can't figure out how to make it work.
One (non-ideal) strategy is to just use the RGui STOP button (or <ESC> or <Ctrl-c> on the console), but this seems cause the tk widget to hang permanently.
Here's a minimal example of the widget based on the tcl/tk examples (http://bioinf.wehi.edu.au/~wettenhall/RTclTkExamples/evalRcode.html):
require(tcltk)
tkscript <- function() {
tt <- tktoplevel()
txt <- tktext(tt, height=10)
tkpack(txt)
run <- function() {
code <- tclvalue(tkget(txt,"0.0","end"))
e <- try(parse(text=code))
if (inherits(e, "try-error")) {
tkmessageBox(message="Syntax error", icon="error")
return()
}
print(eval(e))
}
tkbind(txt,"<Control-r>",run)
}
tkscript()
In the scripting widget if you try executing Sys.sleep(20) and then interrupt from the console, the widget hangs. The same thing happens if one were to run, for example, an infinite loop, like while(TRUE) 2+2.
I think what I'm experiencing may be similar to the bug reported here: https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=14730
Also, I should mention that I'm running this on R 3.0.0 on Windows (x64), so maybe the problem is platform-specific.
Any thoughts on how to interrupt the running script without causing the widget to hang?
It depends on what the script is doing; a script that is sitting waiting for the user to do something is easy to interrupt (since you can make it listen for your interruption message) but a script that is doing an intensive loop is rather more tricky. The possible solutions depend on the version of Tcl inside.
Interpreter Cancellation — Requires 8.6
If you are using Tcl 8.6, you can use interpreter cancellation to stop the script. All you have to do is arrange for:
interp cancel -unwind
to be run, and the script will return control back to you. A reasonable way of doing this would be to use the extra Tcl package TclX (or Expect) to install a signal handler that will run the command when a signal is received:
package require Tcl 8.6
package require TclX
# Our signal handler
proc doInterrupt {} {
# Print a message so you can see what's happening
puts "It goes boom!"
# Unwind the stack back to the R code
interp cancel -unwind
}
# Install it...
signal trap sigint doInterrupt
# Now evaluate the code which might try to run forever
Adding signal handling in earlier versions is possible, but not quite as easy as you can't guarantee that things will return control to you so easily; the stack unwinding isn't there.
Execution Time Limiting — Requires 8.5 (or 8.6)
The other thing you could try is setting an execution time limit on a slave interpreter and running the user script in that slave. The time limit machinery will then guarantee a trap back to you every so often, giving you a chance to check for interruption and a way to do the stack unwinding. This is a considerably more complex method.
proc nextSecond {} {
clock add [clock seconds] 1 second
}
interp create child
proc checkInterrupt {} {
if {["decide if the R code wanted an interrupt"]} {
# Do nothing
return
}
# Reset the time limit to another second ahead
interp limit child time -seconds [nextSecond]
}
interp limit child time -seconds [nextSecond] -command checkInterrupt
interp eval child "the user script"
Think of this mechanism being a lot like how an operating system works, and yes, it can stop a tight loop.
Use a Subprocess — Any version of Tcl
The most portable mechanism is to run the script in a subprocess (with the tclsh program; the exact name varies by version, platform and distribution, but it's all variations on that) and just kill off that subprocess when it is no longer wanted with pskill. The downside of this is that you cannot (easily) carry any state over from one execution to another; subprocesses are pretty isolated from each other. The other methods described above can leave the state able to be accessed from another run: they do a real interrupt, whereas this destroys.
Also, I don't know exactly how to start the subprocess in such a way that you can communicate with it from R while it is still running; system and system2 don't seem to quite give enough control, and hacking something with forking is non-portable. Needs an R expert here. Alternatively, use a Tcl script (running inside the R process) to do it with:
set executable "tclsh"; # Adjust this line
set scriptfile "file/where/you/put/the_user/script.tcl"
# Open a bi-directional pipe to talk to the subprocess
set pipeline [open |[list $executable $scriptfile] "r+"]
# Get the subprocess's PID
set thePID [pid $pipeline]
That is actually reasonably portable to Windows (if not perfectly so) but intermediate states with forking are not.
I seem to have found a solution to prevent the tk widget from hanging by embedding the eval in a tryCatch that handles interrupt conditions. Unfortunately, it requires interruption from the console rather than the widget, but it does work. tryCatch is pretty poorly documented, so I'm putting this out here in case anyone else has similar needs in the future.
require(tcltk)
tkscript <- function() {
tt <- tktoplevel()
txt <- tktext(tt, height=10)
tkpack(txt)
run <- function() {
code <- tclvalue(tkget(txt,"0.0","end"))
e <- try(parse(text=code))
if (inherits(e, "try-error")) {
tkmessageBox(message="Parse error", icon="error")
tkfocus(txt)
return()
}
e <- tryCatch(eval(e),
error = function(errmsg)
tkmessageBox(message=as.character(errmsg), icon="error"),
interrupt = function(errmsg)
tkmessageBox(message=as.character(errmsg), icon="error")
)
print(eval(e))
}
tkbind(txt,"<Control-r>",run)
}
tkscript()
Another strategy I stumbled across is using tools::pskill (in the form pskill(Sys.getpid(), SIGINT) as a tk menu option) to interrupt the process, but - at least on Windows - this terminates the entire R process (including the tk widget). So, that's not a great solution but at least seems to exit everything as an absolute fallback.

Resources