On Oct 24, 2012, at 3:47 PM, Richard D. Morey wrote: > > Richard D. Morey > Assistant Professor > Psychometrics and Statistics > Rijksuniversiteit Groningen / University of Groningen > http://drsmorey.org/research/rdmorey > > On 24/10/12 9:23 PM, Simon Urbanek wrote: >> On Oct 24, 2012, at 3:09 PM, Richard D. Morey wrote: >> >>> On 24/10/12 8:53 PM, Simon Urbanek wrote: >>>> On Oct 24, 2012, at 2:13 PM, Richard D. Morey wrote: >>>> >>>>> This question involves Rook, but I think the answer will be general >>>>> enough that it pays to post here. At any rate, I don't know enough to >>>>> know whether this is a Rook only issue or a general R issue. >>>>> >>>>> Here's what I'd like to do (and indeed, have code that should do this): >>>>> >>>>> 1. Start R, Rook >>>>> 2. Start an analysis via a HTTP request to Rook. This analysis uses >>>>> .Call() to some compiled C code, if that matters. The C code calls a >>>>> callback function to update a variable with its progress. >>>>> 3. While the analysis is happening, use Rook to obtain current status >>>>> with an HTTP request >>>>> >>>> You can't. R doesn't support threading so it's simply not possible to have >>>> an asynchronous eval. The R HTTP server works by simply enqueuing an eval >>>> to run while R is idle, it can't do that if R is busy. (Note that the HTTP >>>> server was *only* designed for the internal help). >>>> >>>> What you can do is have your C code start another thread that reports the >>>> progress when asked e.g. on a socket, but that thread is not allowed to >>>> call any R API so you want that progress to be entirely in your C code. >>> How can I start a new thread? By running R again from the command line, or >>> is there a better way? >>> >> No, you have to use the system thread API like pthreads, NSThread etc. If >> you have to ask about this, you probably don't want to go there ;) - threads >> can be quite dangerous if you are not familiar with them. >> >> Another poor man's solution is to simply have your C code write out a file >> with the progress. Along the same lines you could use a shared object to >> store the progress (e.g. via bigmemory) ... > > I'd be fine with the poor man's solution (maybe with tempfile()?) if I can > get access to the local file via javascript. But I don't think I can, due to > the security limitations of the browser. I may have to rethink this > significantly. >
That should be no problem, you can have another R instance serving the monitoring page (or you can use Rserve's HTTP server and have just one instance with arbitrarily many connections as needed). Cheers, Simon >> >> >>>> Note that if your C code is robust enough, it can call >>>> R_CheckUserInterrupt() to allow external events to happen, but a) your C >>>> code must in that case be prepared for early termination (clean up memory >>>> etc.) and b) I don't remember if the httpd is allowed to run during >>>> interrupt check on all platforms - you may want to check that first. >>> I do use R_CheckUserInterrupt(), but if I understand what you're saying >>> then given that it doesn't work, httpd must not run during the interrupt >>> check. At least, on OSX, which is what I'm testing on. >>> >> Yes, if your code calls R_CheckUserInterrupt() and httpd doesn't respond at >> that point then it may not be allowed to run. On OS X you can try your luck >> with R_ProcessEvents() as well. >> >> Cheers, >> Simon >> >> >> >>>> Cheers, >>>> Simon >>>> >>>> >>>> >>>> >>>>> The problem is that once the analysis starts, Rook does not respond to >>>>> requests. All of the status requests to Rook pile up, and then are >>>>> answered when the analysis (step 2) is done. Here is some example code to >>>>> demonstrate what the issue: >>>>> >>>>> ########## >>>>> >>>>> library(Rook) >>>>> s <- Rhttpd$new() >>>>> s$add( >>>>> name="pingpong", >>>>> app=Rook::URLMap$new( >>>>> '/ping' = function(env){ >>>>> req <- Rook::Request$new(env) >>>>> res <- Rook::Response$new() >>>>> res$write('This is ping.') >>>>> Sys.sleep(20) >>>>> res$finish() >>>>> }, >>>>> '/pong' = function(env){ >>>>> req <- Rook::Request$new(env) >>>>> res <- Rook::Response$new() >>>>> res$write("This is pong.") >>>>> res$finish() >>>>> }, >>>>> '/?' = function(env){ >>>>> req <- Rook::Request$new(env) >>>>> res <- Rook::Response$new() >>>>> res$redirect(req$to_url('/pong')) >>>>> res$finish() >>>>> } >>>>> ) >>>>> ) >>>>> >>>>> s$start(quiet=TRUE) >>>>> s$browse('pingpong') >>>>> >>>>> ############################# >>>>> >>>>> If you request /ping, R runs Sys.sleep() for 20 seconds. This is where my >>>>> .Call() statement would be. While the .Call() (Sys.sleep()) function is >>>>> doing its thing, I need to get Rook to respond on /pong (which would >>>>> simply respond with the progress), but if you run this code, request >>>>> /ping, then immediately request /pong, you'll see that the /pong request >>>>> will not be answered until the Sys.sleep() is done. >>>>> >>>>> Of course, for a progress report to be useful, the requests have to be >>>>> answered immediately. Is this a Rook issue, or an R issue? Or am I asking >>>>> something unreasonable? >>>>> >>>>> ______________________________________________ >>>>> R-devel@r-project.org mailing list >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel >>>>> >>>>> >>> > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel