Процесс уничтожения Bash не завершен - PullRequest
0 голосов
/ 26 октября 2018

У меня есть тема bash, в которой лениво отображаются различные части приглашения.Таким образом, он отображает набор информации в начале, а затем информацию о отложенной загрузке, которая требует времени для загрузки и перезаписи приглашения от фонового процесса.

Теперь, поскольку рендеринг отложенной загрузки является асинхронным, если вы отойдете оттекущий рабочий каталог в другой, в то время как асинхронная часть не была обработана, мы получим неверную информацию в неправильном месте.Пример:

enter image description here

Функция асинхронного рендеринга вызывается:

  # Check the async side of the prompt if available
  set +m
  _render_async &

Теперь, чтобы этого не произошло, я добавилперед тем как отобразить подсказку, проверьте, есть ли у меня какой-либо фоновый процесс, который ожидает рендеринга той асинхронной стороны, которая не находится в текущем каталоге, и уничтожьте ее.

# Check and kill any irreelvant background jobs
# Outdated background jobs are any gaudi::async_render executed on folders
# other than the current working directory $PWD  

export PROMPT_COMMAND="gaudi::kill_outdated_asyncRender; $PROMPT_COMMAND"

# Kill all background gaudi::render_async that are running in the wrong context
# Wrong context is any directory (CWD) that is not the current directory
# USAGE:
#   gaudi::kill_outdated_asyncRender

gaudi::kill_outdated_asyncRender() {
  joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
  IFS=' '
  for job in $joblist; do kill "%$job"; done
}

Теперь это работает отлично, и я не вижунеправильный рендеринг, но я заметил, что теперь завершение bash для функций испорчено, и элементы не отображаются так, как они предназначены:

enter image description here

Как вы можете видеть, элементы завершения находятся не в одной строке, а просто разбиты.Удаление kill_outdated_asyncRender исправляет это поведение, но я все еще не уверен, почему это происходит.

1 Ответ

0 голосов
/ 26 октября 2018

gaudi::kill_outdated_asyncRender устанавливает IFS, но не сбрасывает его. Это имеет глобальные последствия, так как используется в bash для управления делением слов :

Переменная IFS используется в оболочках (Bourne, POSIX, ksh, bash) в качестве разделителя входных полей (или внутреннего разделителя полей). По сути, это строка специальных символов, которые при разбиении строки ввода должны рассматриваться как разделители между словами / полями.

Изменение IFS является распространенным шаблоном, но вы захотите сбросить его:

gaudi::kill_outdated_asyncRender() {
  joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
  local oIFS=$IFS
  IFS=' '
  for job in $joblist; do kill "%$job"; done
  IFS=$oIFS
}

Как общее руководство, держите ваш $PROMPT_COMMAND простым. Очевидно, есть проблема с задержкой, но также довольно сложно отлаживать саму по себе. В связи с этим я бы сделал несколько целевых рекомендаций, чтобы уменьшить вероятность побочных эффектов:

  1. Когда вы запускаете фоновый процесс, запишите его PID в файл. Затем используйте содержимое этого файла в функции kill вместо конвейера jobs | grep.

  2. Вместо того, чтобы вычислять эти значения при смене каталога, предварительно вычисляйте их (в фоновом режиме) при входе в систему и периодически (через cron). У вас также есть команда «обновить», которая обновляет значения синхронно, так что вы всегда можете получить последнее значение, если сомневаетесь в том, что видите.

...