callr
callr copied to clipboard
Running new background process from a parent process that dies before background process terminate
Dear Gábor,
I'm using your beautiful callr package and I'm having trouble because I can't figure out how to execute a background process invoked by a parent process that must terminate its execution immediately after invoking the next one.
In other words, if the parent process ‘dies’ before the child process has finished, the child process is also terminated prematurely.
The only way I have found to make this work is to put a Sys.sleep() into the parent after the callr::r_bg or callr::r_session$call to maintain alive it the time needed by the child process.
(I'm testing it on CentOS7 and R 4.1.2)
Thanks in advance for your help!
Diego
I report 2 functions I wrote invoked by the parent process
# First attempt
runAsync = function(fun_name=NULL, fun_args=list(), src_file=NULL, stdout='|', stderr='|', cmdargs=c('--slave', '--no-save', '--no-restore')) {
wrapper_func = function(src_file, fun_name, fun_args) {
source(src_file)
do.call(get(fun_name), fun_args)
}
callr::r_bg(
func = wrapper_func,
args = list(
src_file = src_file,
fun_name = fun_name,
fun_args = fun_args
),
supervise = FALSE,
stdout = stdout,
stderr = stderr,
cmdargs = cmdargs
)
}
runAsync(
fun_name='my_bg_func',
fun_args=list(par='value1'),
src_file='~/functions_source.R')
#Sys.sleep(35) # only with this does it work
-------------------------------------------------------
# Second attempt
runProcess = function(fun_name=NULL, fun_args=list(), src_file=NULL) {
options = callr::r_session_options()
options$supervise = FALSE
rs = callr::r_session$new(wait=TRUE, options=options)
rs$call(function(fun_name, fun_args, src_file) {
source(src_file)
do.call(get(fun_name), fun_args)
}, list(fun_name, fun_args, src_file))
}
runProcess(
fun_name='my_bg_func',
fun_args=list(par='value1'),
src_file='~/functions_source.R')
#Sys.sleep(35) # only with this does it work
Can you try to create a reproducible example that I can actually run?
callr::r_bg() returns a handle that you can use to manipulate the process and get its output. If you don't have a reference to this handle, then callr (processx) will kill the subprocess. If you want to keep the subprocess alive while the main process is running, then assign the handle to a variable:
proc <- runAsync(...)
If you want to keep the subprocess alive even after the main process has quit, then use cleanup = FALSE, e.g.
callr::r_bg(function()Sys.sleep(100), cleanup = FALSE)
Hello Gábor,
thanks for your rapid response and support!
I've prepared a minimal working example that you can run on your machine.
- A few line of code to schedule a
CRONtask that runs every 1 minute. - An attached R script (rename it with .R extension) that invokes
CRON(parent process) which triggers the background process (child process)
library(cronR)
setwd('/home/peroni/test_folder')
cmd = cronR::cron_rscript(rscript='./cron.test.R', rscript_log='./cron.test.log', log_timestamp=TRUE, log_append=TRUE, workdir=getwd())
cronR::cron_add(command=cmd, frequency='* * * * 1-5', id='cron.test', ask=FALSE)
Dear Gábor,
have you had a chance to test my minimal working example?
Unfortunately, the solution:
callr::r_bg(function()Sys.sleep(100), cleanup = FALSE)
I can't get it to work because the parent process always gets terminated prematurely.
Thanks
Sorry, I meant an example that I can run without any setup and changes. Ideally it would use the callr package only, not extra packages that I am not familiar with. Thanks!
Sure, just run cron.test.R from command line.
Thanks
~/works/callr upkeep-2025-04
❯ Rscript ~/Downloads/cron.test.txt
12:32:56 CRON STARTED
~/works/callr upkeep-2025-04*
❯
What am I supposed to see here?
My problem is that the subprocess started within callr is killed prematurely when the main process ends. I need the subprocess remain alive after the main process ends. It appends as desided just when I run the main process from RStudio and it doesn’t append when I run main process from command line indipendent process (as a scheduled cron process). It looks to me that parameter cleanup doesn’t work as desidered. Is it the same for you? Thanks
I am sorry for being repetitive here, but what is supposed to happen when I run your code? What happens instead?
I can not see printed “Nested Function END” after 10 seconds sleep because the subprocess is killed by main process before it append. Instead when I decomment Sys.sleep(20) in main process I can see “Nested Function END “