Skip to content

Julia 1.10 segfault in threaded PG due to concurrent Libtask callable generation #226

Description

@yebai

On Julia 1.10, threaded Particle Gibbs sampling in Turing can segfault during first-time generation of Libtask-callable objects. See here for an example.

MWE

julia +1.10 --threads=4 --project=test -e '
using Turing, Random, Distributions
using Turing: @model
Turing.setprogress!(false)

@model gdemo_d() = begin
    s ~ InverseGamma(2, 3)
    m ~ Normal(0, sqrt(s))
    1.5 ~ Normal(m, sqrt(s))
    2.0 ~ Normal(m, sqrt(s))
end

chn = sample(Random.Xoshiro(5), gdemo_d(), PG(10), MCMCThreads(), 1, 2; progress=false)
@assert size(chn) == (1, 2)
'

The crash is probabilistic, so repeat in fresh processes:

for i in $(seq 1 200); do
  echo "run $i"
  julia +1.10 --threads=4 --project=test mwe.jl || break
done

Unpatched Libtask failed on run 2/200 with signal 11.

Proposed Fix

Make Libtask.build_callable serialised under a global lock, so only one thread performs callable IR generation/cache population at a time. Sketch:

const build_callable_lock = ReentrantLock()

function build_callable(sig::Type{<:Tuple})
    lock(build_callable_lock)
    try
        # existing build_callable body unchanged
    finally
        unlock(build_callable_lock)
    end
end

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions