Gábor Csárdi
2019-Apr-30 23:03 UTC
[Rd] [External] Re: Background R session on Unix and SIGINT
Unfortunately --interactive also makes the session interactive(), which is bad for me, as it is a background session. In general, I don't want the interactive behavior, but was wondering if I could send as SIGINT to try to interrupt the computation of the background process, and if that does not work, then I would send a SIGKILL and start up another process. It all works nicely, except for this glitch, but I think I can work around it. Thanks, Gabor On Tue, Apr 30, 2019 at 10:55 PM Tierney, Luke <luke-tierney at uiowa.edu> wrote:> > A Simon pointed out the interrupt is recorded but not processed until > a safe point. > > When reading from a fifo or pipe R runs non-interactive, which means > is sits in a read() system call and the interrupt isn't seen until > sometime during evaluation when a safe checkpoint is reached. > > When reading from a terminal R will use select() to wait for input and > periodically wake and check for interrupts. In that case the interrupt > will probably be seen sooner. > > If the interactive behavior is what you want you can add --interactive > to the arguments used to start R. > > Best, > > luke > > On Tue, 30 Apr 2019, G?bor Cs?rdi wrote: > > > OK, I managed to create an example without callr, but it is still > > somewhat cumbersome. Anyway, here it is. > > > > Terminal 1: > > mkfifo fif > > R --no-readline --slave --no-save --no-restore < fif > > > > Terminal 2: > > cat > fif > > Sys.getpid() > > > > This will make Terminal 1 print the pid of the R process, so we can > > send a SIGINT: > > > > Terminal 3: > > kill -INT pid > > > > The R process is of course still running happily. > > > > Terminal 2 again: > > tryCatch(Sys.sleep(10), interrupt = function(e) e) > > > > and then Terminal 1 prints the interrupt condition: > > <interrupt: > > > > > This is macOS and 3.5.3, although I don't think it matters much. > > > > Thanks much! > > G. > > > > On Tue, Apr 30, 2019 at 9:50 PM Simon Urbanek > > <simon.urbanek at r-project.org> wrote: > >> > >> Can you give an example without callr? The key is how is the process stated and what it is doing which is entirely opaque in callr. > >> > >> Windows doesn't have signals, so the process there is entirely different. Most of the WIN32 processing is event-based. > >> > >> Cheers, > >> Simon > >> > >> > >>> On Apr 30, 2019, at 4:17 PM, G?bor Cs?rdi <csardi.gabor at gmail.com> wrote: > >>> > >>> Yeah, I get that they are async. > >>> > >>> What happens is that the background process is not doing anything when > >>> the process gets a SIGINT. I.e. the background process is just > >>> listening on its standard input. > >>> > >>> AFAICT for an interactive process such a SIGINT is just swallowed, > >>> with a newline outputted to the terminal. > >>> > >>> But apparently, for this background process, it is not swallowed, and > >>> it is triggered later. FWIW it does not happen on Windows, not very > >>> surprisingly. > >>> > >>> Gabor > >>> > >>> On Tue, Apr 30, 2019 at 9:13 PM Simon Urbanek > >>> <simon.urbanek at r-project.org> wrote: > >>>> > >>>> Interrupts are not synchronous in R - the signal only flags the request for interruption. Nothing actually happens until R_CheckUserInterrupt() is called at an interruptible point. In you case your code is apparently not calling R_CheckUserInterrupt() until later as a side-effect of the next evaluation. > >>>> > >>>> Cheers, > >>>> Simon > >>>> > >>>> > >>>>> On Apr 30, 2019, at 3:44 PM, G?bor Cs?rdi <csardi.gabor at gmail.com> wrote: > >>>>> > >>>>> Hi All, > >>>>> > >>>>> I realize that this is not a really nice reprex, but anyone has an > >>>>> idea why a background R session would "remember" an interrupt (SIGINT) > >>>>> on Unix? > >>>>> > >>>>> rs <- callr::r_session$new() > >>>>> rs$interrupt() # just sends a SIGINT > >>>>> #> [1] TRUE > >>>>> > >>>>> rs$run(function() 1+1) > >>>>> #> Error: interrupt > >>>>> > >>>>> rs$run(function() 1+1) > >>>>> #> [1] 2 > >>>>> > >>>>> It seems that the main loop somehow stores the SIGINT it receives > >>>>> while it is waiting on stdin, and then it triggers it when some input > >>>>> comes in.... Maybe. Just speculating.... > >>>>> > >>>>> Thanks, > >>>>> Gabor > >>>>> > >>>>> ______________________________________________ > >>>>> R-devel at r-project.org mailing list > >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel > >>>>> > >>>> > >>> > >> > > > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel > > > > -- > Luke Tierney > Ralph E. Wareham Professor of Mathematical Sciences > University of Iowa Phone: 319-335-3386 > Department of Statistics and Fax: 319-335-3017 > Actuarial Science > 241 Schaeffer Hall email: luke-tierney at uiowa.edu > Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
Simon Urbanek
2019-May-01 14:02 UTC
[Rd] [External] Re: Background R session on Unix and SIGINT
Gabor, I think you're talking about two independent things. You can interrupt the computation, no question about that. It's just that if you send an interrupt while you're *not* doing any computations, it will be signaled but not raised until the interrupts are checked since there is no one to check it. This goes back to my original response - the interactive REPL calls R_CheckUserInterrupt(), but the straight stdin-prcessing doesn't (since it's expected to be a script, not interactive prompt). If you just want to clear interrupts before next processing you can either just run R_CheckUserInterrupt() explicitly, or on R side do anything that does that, e.g. to take your example "tryCatch(Sys.sleep(0), interrupt = function(e) e)" will clear it. Cheers, Simon> On Apr 30, 2019, at 7:03 PM, G?bor Cs?rdi <csardi.gabor at gmail.com> wrote: > > Unfortunately --interactive also makes the session interactive(), > which is bad for me, as it is a background session. > > In general, I don't want the interactive behavior, but was wondering > if I could send as SIGINT to try to interrupt the computation of the > background process, and if that does not work, then I would send a > SIGKILL and start up another process. It all works nicely, except for > this glitch, but I think I can work around it. > > Thanks, > Gabor > > On Tue, Apr 30, 2019 at 10:55 PM Tierney, Luke <luke-tierney at uiowa.edu> wrote: >> >> A Simon pointed out the interrupt is recorded but not processed until >> a safe point. >> >> When reading from a fifo or pipe R runs non-interactive, which means >> is sits in a read() system call and the interrupt isn't seen until >> sometime during evaluation when a safe checkpoint is reached. >> >> When reading from a terminal R will use select() to wait for input and >> periodically wake and check for interrupts. In that case the interrupt >> will probably be seen sooner. >> >> If the interactive behavior is what you want you can add --interactive >> to the arguments used to start R. >> >> Best, >> >> luke >> >> On Tue, 30 Apr 2019, G?bor Cs?rdi wrote: >> >>> OK, I managed to create an example without callr, but it is still >>> somewhat cumbersome. Anyway, here it is. >>> >>> Terminal 1: >>> mkfifo fif >>> R --no-readline --slave --no-save --no-restore < fif >>> >>> Terminal 2: >>> cat > fif >>> Sys.getpid() >>> >>> This will make Terminal 1 print the pid of the R process, so we can >>> send a SIGINT: >>> >>> Terminal 3: >>> kill -INT pid >>> >>> The R process is of course still running happily. >>> >>> Terminal 2 again: >>> tryCatch(Sys.sleep(10), interrupt = function(e) e) >>> >>> and then Terminal 1 prints the interrupt condition: >>> <interrupt: > >>> >>> This is macOS and 3.5.3, although I don't think it matters much. >>> >>> Thanks much! >>> G. >>> >>> On Tue, Apr 30, 2019 at 9:50 PM Simon Urbanek >>> <simon.urbanek at r-project.org> wrote: >>>> >>>> Can you give an example without callr? The key is how is the process stated and what it is doing which is entirely opaque in callr. >>>> >>>> Windows doesn't have signals, so the process there is entirely different. Most of the WIN32 processing is event-based. >>>> >>>> Cheers, >>>> Simon >>>> >>>> >>>>> On Apr 30, 2019, at 4:17 PM, G?bor Cs?rdi <csardi.gabor at gmail.com> wrote: >>>>> >>>>> Yeah, I get that they are async. >>>>> >>>>> What happens is that the background process is not doing anything when >>>>> the process gets a SIGINT. I.e. the background process is just >>>>> listening on its standard input. >>>>> >>>>> AFAICT for an interactive process such a SIGINT is just swallowed, >>>>> with a newline outputted to the terminal. >>>>> >>>>> But apparently, for this background process, it is not swallowed, and >>>>> it is triggered later. FWIW it does not happen on Windows, not very >>>>> surprisingly. >>>>> >>>>> Gabor >>>>> >>>>> On Tue, Apr 30, 2019 at 9:13 PM Simon Urbanek >>>>> <simon.urbanek at r-project.org> wrote: >>>>>> >>>>>> Interrupts are not synchronous in R - the signal only flags the request for interruption. Nothing actually happens until R_CheckUserInterrupt() is called at an interruptible point. In you case your code is apparently not calling R_CheckUserInterrupt() until later as a side-effect of the next evaluation. >>>>>> >>>>>> Cheers, >>>>>> Simon >>>>>> >>>>>> >>>>>>> On Apr 30, 2019, at 3:44 PM, G?bor Cs?rdi <csardi.gabor at gmail.com> wrote: >>>>>>> >>>>>>> Hi All, >>>>>>> >>>>>>> I realize that this is not a really nice reprex, but anyone has an >>>>>>> idea why a background R session would "remember" an interrupt (SIGINT) >>>>>>> on Unix? >>>>>>> >>>>>>> rs <- callr::r_session$new() >>>>>>> rs$interrupt() # just sends a SIGINT >>>>>>> #> [1] TRUE >>>>>>> >>>>>>> rs$run(function() 1+1) >>>>>>> #> Error: interrupt >>>>>>> >>>>>>> rs$run(function() 1+1) >>>>>>> #> [1] 2 >>>>>>> >>>>>>> It seems that the main loop somehow stores the SIGINT it receives >>>>>>> while it is waiting on stdin, and then it triggers it when some input >>>>>>> comes in.... Maybe. Just speculating.... >>>>>>> >>>>>>> Thanks, >>>>>>> Gabor >>>>>>> >>>>>>> ______________________________________________ >>>>>>> R-devel at r-project.org mailing list >>>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel >>>>>>> >>>>>> >>>>> >>>> >>> >>> ______________________________________________ >>> R-devel at r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >>> >> >> -- >> Luke Tierney >> Ralph E. Wareham Professor of Mathematical Sciences >> University of Iowa Phone: 319-335-3386 >> Department of Statistics and Fax: 319-335-3017 >> Actuarial Science >> 241 Schaeffer Hall email: luke-tierney at uiowa.edu >> Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu >
Gábor Csárdi
2019-May-01 15:25 UTC
[Rd] [External] Re: Background R session on Unix and SIGINT
On Wed, May 1, 2019 at 4:20 PM Simon Urbanek <simon.urbanek at r-project.org> wrote:> I think you're talking about two independent things. You can interrupt the computation, no question about that. It's just that if you send an interrupt while you're *not* doing any computations, it will be signaled but not raised until the interrupts are checked since there is no one to check it.Right. That's what I suspected originally, so thank you both for confirming it. The difficulty is, when I interrupt the computation that's a race condition, because in the master process I have no idea knowing whether the computation will be finished just before the SIGINT arrives.> This goes back to my original response - the interactive REPL calls R_CheckUserInterrupt(), but the straight stdin-prcessing doesn't (since it's expected to be a script, not interactive prompt). If you just want to clear interrupts before next processing you can either just run R_CheckUserInterrupt() explicitly, or on R side do anything that does that, e.g. to take your example "tryCatch(Sys.sleep(0), interrupt = function(e) e)" will clear it.Yes, that's exactly what I am doing. Thanks again! Gabor [...]