Closed mscottnelson closed 4 years ago
Could you post a sample code that reproduces the issue?
The async_job and it's callback run, but they occurred out of order.
Could you elaborate on this? I might misunderstand but there's no guarantee of execution order when using async tasks.
This is specifically in reference to running the following code from my .zshrc. It does not occur when run in other scenarios. When I run the following code from .zshrc, the while loop never exits (ie output is "Waiting...Waiting...Waiting...Waiting...Waiting...Waiting...Waiting...Waiting...Waiting...Waiting...Waiting..."):
# .zshrc
#!/usr/bin/env zsh
source ./async.zsh
async_init
# Initialize a new worker (with notify option)
async_start_worker my_worker -n
# Create a callback function to process results
COMPLETED=0
completed_callback() {
COMPLETED=$(( COMPLETED + 1 ))
print $@
}
# Register callback function for the workers completed jobs
async_register_callback my_worker completed_callback
# Give the worker some tasks to perform
async_job my_worker print hello
async_job my_worker sleep 0.3
# Wait for the two tasks to be completed
while (( COMPLETED < 2 )); do
print "Waiting..."
sleep 0.1
done
print "Completed $COMPLETED tasks!"
# Output (expected):
# Waiting...
# print 0 hello 0.001583099365234375
# Waiting...
# Waiting...
# sleep 0 0.30631208419799805
# Completed 2 tasks!
# Output (actual):
# Waiting...
# Waiting...
# Waiting...
# Waiting...
# Waiting...
# Waiting...
# Waiting...
However, if I save the same above code to a file, say, ~/example.sh
and then, in my .zshrc, call it this way:
# .zshrc
./example.sh
then it executes as described in the example.
From other experiments, it seems that in this context, for me, the callback is being run before the async job. I do not expect async code to have a guaranteed execution order, but I do expect the callback to reliably run only upon completion of the job that is supposed to trigger the callback on completion.
Could there possibly be something unique to my context that is causing this? I am currently using oh-my-zsh (although I am considering abandoning it).
Just want to clarify that in the scenario I describe above, there is absolutely nothing else in my .zshrc file but the example code.
Hey @mscottnelson, somehow this dropped off my radar, sorry about that.
So the example script is not designed to be source
d as part of an interactive shell, which is what happens when it's put in .zshrc
.
The reason it doesn't work is that zsh-async
detects that the shell is interactive, has ZLE enabled and decides to use a ZLE watcher (zle -F
) to detect when an async task is done. However, a ZLE watcher does not run until ZLE is active, which happens when the prompt is visible and no command is running. Since that while
loop is running before the prompt becomes visible, zsh-async
has no way to automatically detect that a task is complete.
You can fix the issue by manually checking the results in the while
loop (async_process_results my_worker completed_callback
).
It's possible this is my own ignorance.
From an otherwise entirely empty .zshrc, if I call ./example.zsh (filled with a copy of the listing in your README) it performs as expected.
However, if I inline that same script, it appears to get stuck in the while loop and the async functions never run. In the larger context of my existing zshrc, The async_job and it's callback run, but they occurred out of order.
Thank you!