Описание проблемы
На Windows вызовы Git в bsl_index.py выполняются через subprocess.run(..., capture_output=True, timeout=...). Git for Windows обычно запускается через C:\Program Files\Git\cmd\git.exe, который создаёт дочерний процесс mingw64\bin\git.exe.
При истечении timeout Python завершает только непосредственный процесс. Дочерний Git продолжает удерживать унаследованные stdout/stderr pipe-хэндлы, а subprocess.run после kill без дополнительного лимита вызывает communicate() для сбора вывода. В результате timeout формально уже истёк, но вызов может больше никогда не вернуть управление.
Проблема затрагивает все Git-пути: проверку репозитория при rlm_start, получение HEAD и delta для индекса, определение dirty-файлов и git_search.
Шаги воспроизведения
- Запустить на Windows процесс-обёртку с
stdout=PIPE и stderr=PIPE.
- Из обёртки запустить дочерний процесс, наследующий эти pipe, и оставить его работающим дольше родителя.
- Вызвать обёртку через
subprocess.run(..., capture_output=True, timeout=1).
- Дождаться
TimeoutExpired: непосредственный процесс завершается, но дочерний сохраняет pipe открытыми, поэтому финальный сбор вывода зависает.
- В rlm-tools-bsl тот же сценарий может проявиться на медленной или зависшей Git-команде через
rlm_start, обновление индекса либо git_search.
Ожидаемое поведение
Любой Git-timeout должен быть ограничен по wall-clock времени. На Windows необходимо best-effort завершить всё дерево процессов, затем ограниченно собрать/закрыть pipe и пере-бросить исходный subprocess.TimeoutExpired, чтобы существующие fallback-сценарии продолжили работу.
Фактическое поведение
После истечения заданного timeout вызов может зависнуть бессрочно на сборе stdout/stderr, а MCP-запрос или обновление индекса не возвращает ответ.
Логи rlm-сервера
Специфической ошибки может не быть: выполнение не доходит до обработки TimeoutExpired и остаётся заблокированным при закрытии capture pipe.
Окружение
- rlm-tools-bsl: 1.32.1
- Python: воспроизводится на поддерживаемых версиях, включая 3.14
- ОС: Windows
- Формат исходников 1С: не применимо
Дополнительный контекст
Исправление должно быть общим для всех точек запуска Git, без подмены Git executable и без новых зависимостей. Регрессия проверяется реальным Windows-процессом: родитель создаёт наследника, оба удерживают capture pipe; после timeout runner обязан вернуться за ограниченное время и завершить оба PID.
Описание проблемы
На Windows вызовы Git в
bsl_index.pyвыполняются черезsubprocess.run(..., capture_output=True, timeout=...). Git for Windows обычно запускается черезC:\Program Files\Git\cmd\git.exe, который создаёт дочерний процессmingw64\bin\git.exe.При истечении timeout Python завершает только непосредственный процесс. Дочерний Git продолжает удерживать унаследованные stdout/stderr pipe-хэндлы, а
subprocess.runпосле kill без дополнительного лимита вызываетcommunicate()для сбора вывода. В результате timeout формально уже истёк, но вызов может больше никогда не вернуть управление.Проблема затрагивает все Git-пути: проверку репозитория при
rlm_start, получение HEAD и delta для индекса, определение dirty-файлов иgit_search.Шаги воспроизведения
stdout=PIPEиstderr=PIPE.subprocess.run(..., capture_output=True, timeout=1).TimeoutExpired: непосредственный процесс завершается, но дочерний сохраняет pipe открытыми, поэтому финальный сбор вывода зависает.rlm_start, обновление индекса либоgit_search.Ожидаемое поведение
Любой Git-timeout должен быть ограничен по wall-clock времени. На Windows необходимо best-effort завершить всё дерево процессов, затем ограниченно собрать/закрыть pipe и пере-бросить исходный
subprocess.TimeoutExpired, чтобы существующие fallback-сценарии продолжили работу.Фактическое поведение
После истечения заданного timeout вызов может зависнуть бессрочно на сборе stdout/stderr, а MCP-запрос или обновление индекса не возвращает ответ.
Логи rlm-сервера
Окружение
Дополнительный контекст
Исправление должно быть общим для всех точек запуска Git, без подмены Git executable и без новых зависимостей. Регрессия проверяется реальным Windows-процессом: родитель создаёт наследника, оба удерживают capture pipe; после timeout runner обязан вернуться за ограниченное время и завершить оба PID.