-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bugs in async code #753
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,49 +9,59 @@ _zsh_autosuggest_async_request() { | |
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID | ||
|
||
# If we've got a pending request, cancel it | ||
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then | ||
# Close the file descriptor and remove the handler | ||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- | ||
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD | ||
|
||
# We won't know the pid unless the user has zsh/system module installed | ||
if [[ -n "$_ZSH_AUTOSUGGEST_CHILD_PID" ]]; then | ||
# Zsh will make a new process group for the child process only if job | ||
# control is enabled (MONITOR option) | ||
if [[ -o MONITOR ]]; then | ||
# Send the signal to the process group to kill any processes that may | ||
# have been forked by the suggestion strategy | ||
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null | ||
if (( _ZSH_AUTOSUGGEST_CHILD_PID )); then | ||
kill -TERM -- $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null | ||
_ZSH_AUTOSUGGEST_CHILD_PID= | ||
fi | ||
|
||
_ZSH_AUTOSUGGEST_ASYNC_FD= | ||
|
||
{ | ||
# Fork a process to fetch a suggestion and open a pipe to read from it | ||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( | ||
# Suppress error messages | ||
exec 2>/dev/null | ||
|
||
# Tell parent process our pid | ||
if (( ${+sysparams} )); then | ||
echo ${sysparams[pid]} || return | ||
else | ||
# Kill just the child process since it wasn't placed in a new process | ||
# group. If the suggestion strategy forked any child processes they may | ||
# be orphaned and left behind. | ||
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null | ||
echo || return | ||
fi | ||
fi | ||
fi | ||
|
||
# Fork a process to fetch a suggestion and open a pipe to read from it | ||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( | ||
# Tell parent process our pid | ||
echo $sysparams[pid] | ||
# Fetch and print the suggestion | ||
local suggestion | ||
_zsh_autosuggest_fetch_suggestion "$1" | ||
echo -nE - "$suggestion" | ||
) || return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @romkatv Can you elaborate on the addition of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose one could read the source code of the builtins I think a better question is what the code should do when |
||
|
||
# Fetch and print the suggestion | ||
local suggestion | ||
_zsh_autosuggest_fetch_suggestion "$1" | ||
echo -nE "$suggestion" | ||
) | ||
# There's a weird bug here where ^C stops working unless we force a fork | ||
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 | ||
autoload -Uz is-at-least | ||
is-at-least 5.8 || command true | ||
|
||
# There's a weird bug here where ^C stops working unless we force a fork | ||
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 | ||
autoload -Uz is-at-least | ||
is-at-least 5.8 || command true | ||
# Read the pid from the child process | ||
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD || return | ||
|
||
# Read the pid from the child process | ||
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD | ||
# Zsh will make a new process group for the child process only if job | ||
# control is enabled (MONITOR option) | ||
if [[ -o MONITOR ]]; then | ||
# If we need to kill the background process in the future, we'll send | ||
# SIGTERM to the process group to kill any processes that may have | ||
# been forked by the suggestion strategy | ||
_ZSH_AUTOSUGGEST_CHILD_PID=-$_ZSH_AUTOSUGGEST_CHILD_PID | ||
fi | ||
|
||
# When the fd is readable, call the response handler | ||
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response | ||
# When the fd is readable, call the response handler | ||
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response | ||
} always { | ||
# Clean things up if there was an error | ||
if (( $? && _ZSH_AUTOSUGGEST_ASYNC_FD )); then | ||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- | ||
_ZSH_AUTOSUGGEST_ASYNC_FD= | ||
_ZSH_AUTOSUGGEST_CHILD_PID= | ||
fi | ||
} | ||
} | ||
|
||
# Called when new data is ready to be read from the pipe | ||
|
@@ -61,16 +71,20 @@ _zsh_autosuggest_async_response() { | |
emulate -L zsh | ||
|
||
local suggestion | ||
if (( $1 == _ZSH_AUTOSUGGEST_ASYNC_FD )); then | ||
_ZSH_AUTOSUGGEST_ASYNC_FD= | ||
_ZSH_AUTOSUGGEST_CHILD_PID= | ||
if [[ $# == 1 || $2 == "hup" ]]; then | ||
# Read everything from the fd | ||
IFS='' read -rd '' -u $1 suggestion | ||
fi | ||
fi | ||
|
||
if [[ -z "$2" || "$2" == "hup" ]]; then | ||
# Read everything from the fd and give it as a suggestion | ||
IFS='' read -rd '' -u $1 suggestion | ||
zle autosuggest-suggest -- "$suggestion" | ||
# Always remove the handler and close the fd | ||
zle -F $1 | ||
exec {1}<&- | ||
|
||
# Close the fd | ||
exec {1}<&- | ||
if [[ -n $suggestion ]]; then | ||
zle autosuggest-suggest -- "$suggestion" | ||
fi | ||
|
||
# Always remove the handler | ||
zle -F "$1" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you've also removed the check of
[[ -o MONITOR ]]
. Was that intentional and if so can you give some reasoning for it? I had never fully tested the different cases there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check for
MONITOR
is still there. It used to be performed before invokingkill
, which isn't quite right. I moved it to the proper point (when forking). This makes a difference if the option is changed between forking and killing. I should've this change in the description.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Friendly ping.