Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting "Error in appList[[i]] : subscript out of bounds" when refreshing server #37

Open
aaronolsen opened this issue Nov 1, 2017 · 1 comment

Comments

@aaronolsen
Copy link

Hi Jeffrey,

Background and a thank you
I've just started using Rook to create a web interface for a "digitizing application". I was previously using shiny because I was unaware of Rook but I was basically using shiny just to send/receive data between the server and R - I designed the entire html/javascript interface myself (see the current version here: https://aaronolsen.github.io/software/digitizing.html). Of course for that shiny is overkill. I now realize Rook is sufficient for what I need and will in fact be better because I can access multiple local directories using 'File$new' (e.g. to load images from the users computer). With shiny I've been having to copy over everything that I want to access to the 'www' folder. This is all to say that Rook is a game-changer for me - thank you very much for writing it!

The code that generates the error
Here is the code I'm running (Rook v1.1-1, R v3.4.2, Safari v10.0.2) that generates the error - it's a server that provides access to my Downloads folder. I've reduced it down to a near minimal working example with some extra bits to confirm things are working.

library(Rook)
tryCatch({ R.server$stop() }, error = function(e) {}, warning = function(e) {})
R.server <<- Rhttpd$new()
R.server$add(app = File$new('/Users/aaron/Downloads'), name = "pic_dir")
R.server$start(quiet=TRUE)
iter <<- 0
Rook.app <- function(env) {
	iter <<- iter + 1
	print(paste0('Rook.app ', iter))
	request <- Request$new(env)
	response <- Response$new()
	write.HTML(response, R.server)
	response$finish()
}
write.HTML <- function(response, server){
	response$write("<form method=\"POST\">")
	response$write("<input type=\"submit\" value=\"Submit\" name=\"submit_button\">")
}
R.server$add(app = Rook.app, name = "Rook app")
R.server$browse("Rook app")

The error
When I run this code I periodically get the following error message in the R console.

Error in appList[[i]] : subscript out of bounds

I don't get the error every time I call the server. Sometimes I have to submit a request multiple times or close/open the server multiple times to get the error. Less frequently, the error just spontaneously occurs while the server is running with no user interaction. The error causes the server to crash so I have to close the browser window and re-start.

This may have something to do with me making the server a global variable. But I want to use a global variable so that I can access the server outside the function to stop it. That's why I've included a R.server$stop() command before I start the server (in case it's still running).

A solution
I tracked down the source of the error to the 'finalize' method of the 'Rhttpd' class. Somehow this method is being called while the server is running but when it gets called seems somewhat unpredictable. It seems all this method does is remove the apps associated with the server. So to solve the issue I wrote a revised 'Rhttpd' class ('Rhttpd2') with the 'finalize' method actions commented out. 'Rhttpd2' is the same as the current version of 'Rhttpd' with the following changes:

Rhttpd2 <- setRefClass(
   'Rhttpd2',
. . .
   finalize = function(){
#      if (length(appList) == 0) return()
#      for (i in rev(1:length(appList))){
#         remove(appList[[i]])
#      }
   },
. . . 
   listenPort <<- suppressMessages(tools::startDynamicHelp(TRUE))
. . .
   stop = function(){
      listenPort <<- suppressMessages(tools::startDynamicHelp(FALSE))
   },

And here is the revised code that sets up and starts the server (assuming the revised 'Rhttpd2' above has been loaded).

library(Rook)
tryCatch({ R.server$stop() }, error = function(e) {}, warning = function(e) {})
tryCatch({ remove(R.server) }, error = function(e) {}, warning = function(e) {})
R.server <<- Rhttpd2$new()
R.server$add(app = File$new('/Users/aaron/Downloads'), name = "pic_dir")
R.server$start(quiet=TRUE)
iter <<- 0
Rook.app <- function(env) {
	iter <<- iter + 1
	print(paste0('Rook.app ', iter))
	request <- Request$new(env)
	response <- Response$new()
	write.HTML(response, R.server)
	response$finish()
}
write.HTML <- function(response, server){
	response$write("<form method=\"POST\">")
	response$write("<input type=\"submit\" value=\"Submit\" name=\"submit_button\">")
}
R.server$add(app = Rook.app, name = "Rook app")
R.server$browse("Rook app")

At this point I don't have a need for stopping and re-starting the same server. So for me when I stop the server I'm content to simply remove the entire server and re-define everything when I want to start it up again. That's why I've also included a remove(R.server) command after stopping the server. This should cover everything that the 'finalize' method was doing previously. If the user quits R I'm assuming R.server is also removed so I see no way the server object would stick around.

I see you haven't been developing Rook actively for some time now - which is totally OK - so I don't necessarily expect a response. If you do have a chance to look into this that'd be great. But I'm also posting here so that if others encounter the same error this will give them an idea of how to find a solution.

Many thanks,
Aaron

@kachunwong
Copy link

kachunwong commented Jun 24, 2018

R.server$remove(all=TRUE)

can also work without modifying the original package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants