Task termination

I’m trying to get the following to work (or something like it)

function execute(f::Function)
    exec = Executor()

    t = schedule(@task try
            while true
                run!(exec)
                yield()
            end
        catch e
            shutdown!(exec)
            println("done")
            if !isa(e, InterruptException)
                println("Shutdown Executor: $e")
                rethrow(e)
            end
        end
    )

    try
        f(exec)
    finally
        println("shutting down")
        #schedule(@task Base.throwto(t, InterruptException()))
        Base.throwto(t, InterruptException())
        wait(t)
    end
end

But I’m getting strange error I cannot make sense of:
“WARNING: Workqueue inconsistency detected: popfirst!(Workqueue).state != :queued”
or everything hangs.

I get the feeling that maybe the main task not a Task or its acting differently? I’ve read on discourse that you should schedule the throwto, but this also does not work.

What would be a good way to achieve something like this?

1 Like
function execute(f::Function)
    t = schedule(@task try
            while true
                yield()
            end
        catch e
            println("done")
            if !isa(e, InterruptException)
                println("Shutdown Executor: $e")
                rethrow(e)
            end
        end
    )

    try
        f()
    finally
        println("shutting down")
        #schedule(@task Base.throwto(t, InterruptException()))
        Base.throwto(t, InterruptException())
        wait(t)
    end
end

execute(()->println("hello"))

This will give the warning “WARNING: Workqueue inconsistency detected: popfirst!(Workqueue).state != :queued” and then hangs.

I’m guessing that yield does not do what I expect it to do. Changing yield to sleep(0) and using the schedule(@task throwto) method seems to do the what I want, but I cannot explain why it needs to be that complicated. Also I don’t want to sleep…

Thanks in advance

Thanks for the update, I can reproduce this behavior. I also think I found the explanation, although it may not be totally gratifying: https://github.com/JuliaLang/julia/issues/25353#issuecomment-354802975

1 Like

replacing the throwto with

schedule(t, InterruptException(), error=true)

gives

julia> execute(()->println("hello"))
hello
shutting down
done

I use this schedule(...) a fair bit in some of my code and it “mostly works” though sometimes there can be synchronization issues in which case adding a short sleep(...) can help iron out issues (it can be a bit messy but I think there is the project of having a more robust system a la trio in the future, see also this discussion).

4 Likes

Random comment: FYI it should be rethrow() not rethrow(e).

See here

Does anyone have any good references to this subject area in Julia? Documentation on tasks and async is quite minimal.

It’s hard to build a mental model of how async works at a low level, so therefore it’s hard to figure out exactly how to program using these ideas.

1 Like

Please open a new topic if you have a related question, the last post on this thread was over 5 years ago and any new reply pings everyone who took part back then.

3 Likes