UPDATE: 2022-10-28 19:59:49

はじめに

関数の実行をタイムアウトさせたい。プロセスIDをどうこうして実現できるとか思って、5時間くらい色々頑張ったが、検索したらでてきた。がーさすRとともに悲しい。

タイムアウトさせる

タイムアウトで指定した秒数で処理が完了しなければ、関数の実行を中止する。

library(R.utils)

R.utils::withTimeout(sum((1:1e3)^2), timeout = 3, onTimeout = "silent")
[1] 333833500

R.utils::withTimeout(sum((1:1e8)^2), timeout = 3, onTimeout = "silent")
NULL

中身はこんな感じ。

> withTimeout
function (expr, substitute = TRUE, envir = parent.frame(), timeout, 
    cpu = timeout, elapsed = timeout, onTimeout = c("error", 
        "warning", "silent"), ...) 
{
    if (substitute) 
        expr <- substitute(expr)
    if (!is.environment(envir)) 
        throw("Argument 'envir' is not a list: ", class(envir)[1L])
    cpu <- Arguments$getNumeric(cpu, range = c(0, Inf))
    elapsed <- Arguments$getNumeric(elapsed, range = c(0, Inf))
    onTimeout <- match.arg(onTimeout)
    setTimeLimit(cpu = cpu, elapsed = elapsed, transient = TRUE)
    on.exit({
        setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
    })
    tryCatch({
        eval(expr, envir = envir)
    }, error = function(ex) {
        msg <- ex$message
        pattern <- gettext("reached elapsed time limit", "reached CPU time limit", 
            domain = "R")
        pattern <- paste(pattern, collapse = "|")
        if (regexpr(pattern, msg) != -1L) {
            ex <- TimeoutException(msg, cpu = cpu, elapsed = elapsed)
            if (onTimeout == "error") {
                throw(ex)
            }
            else if (onTimeout == "warning") {
                warning(getMessage(ex))
            }
            else if (onTimeout == "silent") {
            }
        }
        else {
            throw(ex)
        }
    })
}
<bytecode: 0x5565ed6a2300>
<environment: namespace:R.utils>