Sorry for the late reply, it took a couple of iterations (and some days off) to find a feasible solution without splitting the helper function into two -- please see below if interested.
On Sat, Jun 8, 2019 at 6:50 PM Duncan Murdoch <murdoch.dun...@gmail.com> wrote: > > On 08/06/2019 9:55 a.m., Gergely Daróczi wrote: > > On Sat, Jun 8, 2019 at 2:13 PM Duncan Murdoch <murdoch.dun...@gmail.com> > > wrote: > >> > >> On 08/06/2019 7:42 a.m., Gergely Daróczi wrote: > >>> Dear All, > >>> > >>> I'm using "reg.finalizer" in a function that is to be called in R scripts > >>> to do some cleanup on success. I have not found a way to run the function > >>> only if the script run without errors, so when the exit code is expected > >>> to > >>> be 0. > >>> > >>> What I've tried is checking "geterrmessage()", but unfortunately it's not > >>> perfect: if an error was handled with eg "tryCatch" previously, that > >>> message still shows up there. > >>> > >>> Is there any better way of figuring out in "reg.finalizer" or ".Last" if > >>> the session run OK or exiting with !0 exit code? > >> > >> Can't you just put the line to run it as the last line of your script? > >> You won't get there if there was an error. > > > > Thank you very much, Duncan, but unfortunately, that's not feasible. > > > > "reg.finalizer" is called from a function early in the script, which > > function first checks when the same script last run and optionally > > exists early. > > > If that optional early exit (within the helper function) doesn't > > happen, then the "reg.finalizer" call sets a status update when the R > > script has finished, but that should only happen if the script run > > without any problems. > > > > Of course, this helper could be split into two -- (1) function call at > > the beginning of the script and (2) another at the end, but it would > > be much less elegant and error-prone. > > > > I know I'm trying to hack-in some features in my R scripts that should > > be better handled by an external job scheduler, but I hope this is > > doable. > > I still think you're using reg.finalizer() in a way it's not designed to > work, and this makes it more complicated than necessary. The strategy > of splitting into two seems safer to me: you never know when a > finalizer will be called, because it is triggered by garbage > collections, and those can happen asynchronously, not under your control. Yes, you are absolutely right -- still, I really wanted to make this work by calling only one function at the beginning of an R script (actually, hundreds of R scripts and without an explicit R function call, but doing that in a package's .onLoad function). What I came up with is probably not too elegant ... and might have some edge cases, but seems to do the trick, so thus turned out to be a reasonable solution for now: - overriding the default "error" option to set an env var - check that env var at the end of the script via "reg.finalizer" triggered on exit Quick example: ```r library(logger) options(error = function() { Sys.setenv(R_ERROR_HAPPENED = TRUE) quit(status = 1) }) reg.finalizer(e = environment(), f = function(...) { if (Sys.getenv('R_ERROR_HAPPENED') != '') { log_error(skip_formatter(paste('Seems like there was an error previously:', geterrmessage()))) } else { log_info('All good!') } }, onexit = TRUE) 1 + dasf ``` > > It is nice to have all code for some purpose in one place, so if you > really want that, you could put together your own explicitly called > finalizer, something like this: > > finalizers <- list() > > addFinalizer <- function(fn) { > finalizers <<- c(finalizers, list(fn)) > } > > runFinalizers <- function() { > for (i in rev(seq_along(finalizers))) { # Run in reverse order > finalizers[[i]]() # Call the finalizer > finalizers[[i]] <- NULL # Allow related objects to be released > } > } > > > In the place you now call reg.finalizer(), you call addFinalizer() > instead; so all code specific to that task remains local. At the end of > your script if things have been successful, you call runFinalizers(). > > Duncan Murdoch > > > > > > > > >> > >> > >> The point of reg.finalizer is to run code even if there was an error; > >> your situation is much simpler. > >> > >> Duncan Murdoch > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel