rexyai / RestRserve

R web API framework for building high-performance microservices and app backends
https://restrserve.org
275 stars 32 forks source link

Needs Graceful shutdown [feature request] #158

Closed vikram-rawat closed 4 years ago

vikram-rawat commented 4 years ago

Running an RestRserver on Rstudio crashes the studio and it has be opened back. Running it from shell also has the same problem that you just have to close the entire shell and reopen it.

It is actually very cumbersome. Please at least think about graceful shutdown of the app.

dselivanov commented 4 years ago

Unfortunately we can't do much with Rserve backend. It would be possible with httpuv backend, but this is not a priority at the moment.

s-u commented 4 years ago

@dselivanov Rserve supports graceful shutdown, can you clarify the requirements?

dselivanov commented 4 years ago

@s-u I believe the concern is about issues with GUI after shutting down Rserve (by sending SIGINT to the host R process from where Rserve launched).

Also I see that there is shutdown command for "most graceful" shutdown which can be issued by client. But for standard unix signals the best we can do is SIGINT, right?

s-u commented 4 years ago

I don't know how you start Rserve, but in either case it supports any of SIGINT, SIGHUP and SIGKILL to signal shutdown. If you run it as a separate process then I don't see why it should affect the GUI. I don't think you can start Rserve inside an RStudio session (run.Rserve()), because RStudio is known to blow up on fork() (most often noticed when users use mc* functions in parallel), that's a known issue in RStudio.

As for terminal, it may be just that you have client processes that are still also accessing the terminal. You should be able to simply close std* descriptors to avoid that since you probably don't want stdin for the forked workers anyway. If you have an actual use-case, let me know and I can have a look. In principle any mechanism is ok, it is literally just setting a active variable to 0 to shut it down so it can be done in many different ways.

dselivanov commented 4 years ago

I don't know how you start Rserve

With run.Rserve() from within active R session.

don't think you can start Rserve inside an RStudio session (run.Rserve())

It one can run run.Rserve(), but then after Rserve shutdown (kill SIGINT) Rstudio crashes. But yes, that's Rstudio issue which I don't want to touch here.

You should be able to simply close std* descriptors to avoid that since you probably don't want stdin for the forked workers anyway. If you have an actual use-case, let me know and I can have a look. In principle any mechanism is ok, it is literally just setting a active variable to 0 to shut it down so it can be done in many different ways.

Could you please elaborate on this? I see close.all.stdio Rserve config option, but I don't want to disable stdout since logs by default are written to stdout.

s-u commented 4 years ago

I was thinking something like parallel:::closeFD(0L) to close stdin once the client connects. Note that run.Rserve() was really only intended for debugging, it may cause a lot of issues, because it's inheriting a potentially interactive session which is unsuitable for a server process. Only Rserve() was intended to be used for real applications. (Technically, there is a difference: Rserve embeds libR and has control over the entire process; run.Rserve() loads pieces of Rserve in the form of Rserve.so into the session and starts the server in the current R without any control over the session).

Also note that using stdout for logs is not a very good idea as it is shared by all children and the R session, so the subprocesses can die because of SIGPIPE if the output is not correctly consumed. Any reason why you don't use a file (or pipe or socket) for logging? I would definitely separate the I/O of the worker processes from the session or else it will be a mess.