I have a function that listens to a redis stream in a while loop but it hangs and doesnt release back to the REPL. I managed to create a MWE.
function foo()
i = 0
while true
if i==0
continue # hangs
#nothing # doesnt hang
end
println(i)
sleep(5)
i = i+1
end
end
@async foo() # this hangs
Sukera
2
In your example, i
is always 0
, so the branch with continue
is always hit. If you want your code to yield to some other asynchronous code, explicitly call yield()
.
Also, how many threads are you starting julia with and what version are you running? On some older versions, the REPL didn’t run on its own thread by default, so if another task hogs the sole thread without yielding, it’ll never regain control by itself.
1 Like
Benny
3
In other words, your code is stuck looping these lines indefinitely, you never reach the sleep
that goes back to the task queue. You probably intended the i = i+1
to happen earlier, maybe at the very beginning of the while true
loop (you sure you want that to go on forever though?).
The expected behavior would be that the function foo
would just get put into a task and move on, freeing up the REPL.
I run into the same issue if I do
julia> function foo()
i = 0
while true
i += 1
end
end
foo (generic function with 1 method)
julia> @async foo() #hangs
Benny
5
Your REPL is freed, it just yields to the scheduler when idle and ends up running your task, which has nothing in the loop or the method that would yield back to the scheduler.
foo()
is getting put into a task, but it runs on the main thread, and it’s fast enough to use the thread’s whole resources, which starves the thread for the REPL. If you use something like
function foo()
i = 0
while true
sleep(.1)
end
end
then you’ll see control returned to the REPL as promised.
Julia uses cooperative scheduling, so by default you’re not going to see anything interrupt foo()
if it continuously has work to do.
You could start it on another thread:
Threads.@spawn foo()
Or use an explicit yield() (the task will still keep working whenever there’s nothing else to do):
function yielding_foo()
i = 0
while true
i = i + 1
yield()
end
end
@async yielding_foo()
2 Likes