From jeroen.ooms at stat.ucla.edu  Thu May 16 21:34:13 2013
From: jeroen.ooms at stat.ucla.edu (Jeroen Ooms)
Date: Thu, 16 May 2013 12:34:13 -0700
Subject: [Rd] setTimeLimit sometimes fails to terminate idle call in R
In-Reply-To: <9187D1C3-2FDD-4432-9FCE-FB4CEDC53A92@r-project.org>
References: <CABFfbXsBsTt4aHvTePo+0iCnkQ3df+RwcpwogXH40RmtB=BYiA@mail.gmail.com>
	<9187D1C3-2FDD-4432-9FCE-FB4CEDC53A92@r-project.org>
Message-ID: <CABFfbXsru+qC5XRnz2aLnPkUz9XwoQtkGgDWudH3jcPDXDvTPg@mail.gmail.com>

Thank you for the elaborate response. I am going to look into the quartz code.

> On top of my head I can't think of a built-in solution in R at this point (even though it could be argued that R might install a handler itself when the limit is set ...).

Yes, I think this would greatly enhance the usability of setTimeLimit.

> But note that this is really just a special case of of Sys.sleep(). If you actually run R code, then ProcessEvents is triggered automatically during the evaluation (or in interruptible C code).

Well, the main use case that I have in mind is where the process is
stuck waiting for some child process or socket. For example, I would
like to implement a timeout parameter for psockcluster nodes,
equivalent to mccollect timeout. Below a poc that I hacked together,
which works on windows, but not linux/osx for above reasons.

eval_psock <- function(expr, envir=parent.frame(), timeout=60){
  #create a child process
  cluster <- parallel::makePSOCKcluster(1);
  child <- cluster[[1]];
  parallel:::sendCall(child, eval, list(quote(Sys.getpid())));
  pid <- parallel:::recvResult(child);

  #set the timeout
  setTimeLimit(elapsed=timeout, transient=TRUE);
  on.exit({
    setTimeLimit(cpu=Inf, elapsed=Inf, transient=FALSE);
    tools::pskill(pid); #win
    tools::pskill(pid, tools::SIGKILL); #nix
    parallel:::stopNode(child);
  });

  #send the actual call
  parallel:::sendCall(child, eval, list(expr=substitute(expr),
    envir=as.list(envir)));
  myresult <- parallel:::recvResult(child);

  #reset timelimit
  setTimeLimit(cpu=Inf, elapsed=Inf, transient=TRUE);

  #forks don't throw errors themselves
  if(is(myresult,"try-error")){
    #snow only returns the message, not an error object
    stop(myresult, call.=FALSE);
  }

  #send the buffered response
  return(myresult);
}

test <- function(){
  n <- 1e8;
  k <- 1e4;
  #this should take more than 10 sec
  eval_psock(svd(matrix(rnorm(n), k)), timeout=10);
}

system.time(test());



[Rd] setTimeLimit sometimes fails to terminate idle call in R
Jeroen Ooms