2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Julia コルーチン内でのエラーを捕捉する

Posted at

Juliaのコルーチン

Juliaには強力なコルーチン機構がある。1つのスレッド内で複数のコルーチンを並行に動作させることで、IOを効率的にハンドルすることができる。しかしコルーチン内で発生したエラーは、エラーが起こった後でタスクを表示したりしないと顕在化しない。

julia> t = @async begin sleep(1); error() end
Task (runnable) @0x000000010bdf6590

タスクに対してwaitすればスタックトレースが出る。

julia> wait(t)
ERROR: TaskFailedException
Stacktrace:
 [1] wait(t::Task)
   @ Base ./task.jl:352
 [2] top-level scope
   @ REPL[14]:1

    nested task error: 
    Stacktrace:
     [1] error()
       @ Base ./error.jl:44
     [2] (::var"#15#16")()
       @ Main ./REPL[13]:1

しかし、複数の長時間実行されるタスクを並行に実行する場合にはwaitはできない。どちらかに対してwaitするとそこでブロックしてしまうからだ。下の例ではt0が終了するまでは t1のエラーが捕捉できない。そもそも t0 が終了するとは限らないので、その場合はt1のエラーは捕捉できないことになる。

t0 = @async begin sleep(10); error() end
t1 = @async begin sleep(1); error() end
wait(t0)
wait(t1)

@sync

どうしたものか、調べてみたらそのものズバリのissueがあった。

@sync を使うと、そのブロック内で起動されたタスクすべての終了を同時に待つ事ができる。

@sync begin
    t0 = @async begin sleep(10); error() end
    t1 = @async begin sleep(1); error() end
end

しかし、どうもすべてが終了するまでエラーが表示されないようで、個別に待つのとあまり変わらない。

ラッパタスクを使う

これを解決する方法も上のissueに書かれている。
対象タスクを、そのタスクをwaitするだけのタスクでラップすればいい。

@async begin
    t = @async begin sleep(1); error(); true end
    try 
        wait(t)
    catch
        display(t)
    end
end

さらにすすめて、これをマクロ化したものもあった。

macro monitored_async(expr)
    quote
        @async begin
            t = @async $(esc(expr))
            try
                wait(t)
            catch
                display(t)
            end
        end
    end
end

これを@asyncの代わりに使えばいい。

julia> @monitored_async begin sleep(1); error(); true end
Task (runnable) @0x000000010cc5e0e0

julia> Task (failed) @0x000000010cc5f210

Stacktrace:
 [1] error()
   @ Base ./error.jl:44
 [2] macro expansion
   @ ./REPL[30]:1 [inlined]
 [3] (::var"#42#44")()
   @ Main ./REPL[28]:4

便利。。@async をそのまま使うと、すべてのエラーがサイレントに握りつぶされてしまって非常に不便だったので、助かる。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?