Mocking.jl icon indicating copy to clipboard operation
Mocking.jl copied to clipboard

Asynchronous tasks can accidentally call patched functions

Open omus opened this issue 4 years ago • 5 comments

In a scenario where an background asynchronous task is calling a function using @mock and a patch is applied during that time the async task can call the patched function instead of the original:

julia> using Mocking

julia> Mocking.activate()

julia> f() = 1
f (generic function with 1 method)

julia> function g(name, n)
           for i in 1:n
               x = @mock f()
               println(name, ": ", x)
               sleep(1)
           end
       end
g (generic function with 1 method)

julia> p = @patch f() = 2

Patch{typeof(f)}(f, var"##f_patch#259")

julia> @async g("async", 5)
async: Task (runnable) @0x000000012f5973101


julia> apply(p) do
           g("apply", 1)
       end
apply: 2
async: 2

julia> async: 1
async: 1
async: 1
julia>

omus avatar Sep 17 '21 20:09 omus

We might want to push the variable that says if we are mocking or not into a dynamically scoped context from ContextVariablesX.jl I think that supports tasks and threads. We use it in Checkpoints.jl as of https://github.com/invenia/Checkpoints.jl/pull/15

oxinabox avatar Oct 01 '21 17:10 oxinabox

I've confirmed that ContextVariablesX.jl does fix the issue as demonstrated above. I'll work on a PR for this.

@oxinabox I appreciate you bringing that package to my attention ❤️

omus avatar Oct 01 '21 21:10 omus

Unfortunately using ContextVariablesX.jl doesn't play nice with @test_logs or @test_deprecated so using that had to be reverted.

omus avatar Oct 14 '21 16:10 omus

@tkf any ideas?

oxinabox avatar Oct 14 '21 18:10 oxinabox

omus already figured it out. But, linking the discussion for the record: https://github.com/tkf/ContextVariablesX.jl/issues/16#issuecomment-943494351

tkf avatar Oct 14 '21 19:10 tkf

Issue was fixed in https://github.com/JuliaTesting/Mocking.jl/pull/112 but requires Julia 1.11

omus avatar Jul 15 '24 15:07 omus