-
Notifications
You must be signed in to change notification settings - Fork 107
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
Зависает Процесс.ПотокВывода.Прочитать при вызове "долгих" команд #402
Comments
|
До исправления задачи по апи потоков ничего 100% хорошего не выйдет. Могу порекомендовать использовать не Прочитать, а ПрочитатьСтроку |
А 100 вариант использовать перенаправление в файл |
А возможность перенаправить в файл есть? |
ПрочитатьСтроку точно так же зависает. От него как раз и перешли Прочитать, чтобы реже вызывать чтение из буфера |
Бяда. Задачка на это есть, надо уже сделать. Там просто низкоуровневое все и тестировать тяжело. Займусь |
Можно чуть проще и без гита: Функция ВыполнитьДинамически(КолИтераций)
ИмяВремФайла = ПолучитьИмяВременногоФайла("os");
ТекстФайла = СтрШаблон("Сообщить("">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Количество итераций %1"");", КолИтераций);
Для й = 1 По КолИтераций Цикл
ТекстФайла = ТекстФайла + СтрШаблон("Сообщить(""Итерация № %1"");", й) + Символы.LF;
КонецЦикла;
Текст = Новый ТекстовыйДокумент;
Текст.ДобавитьСтроку(ТекстФайла);
Текст.Записать(ИмяВремФайла);
СтрокаЗапуска = "oscript " + ИмяВремФайла;
Процесс = СоздатьПроцесс(СтрокаЗапуска, , Истина, Истина);
Процесс.Запустить();
Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные Цикл
ОчереднаяСтрокаВывода = Процесс.ПотокВывода.ПрочитатьСтроку();
сообщить("Из процесса: " + ОчереднаяСтрокаВывода);
КонецЦикла;
УдалитьФайлы(ИмяВремФайла);
КонецФункции
ВыполнитьДинамически(50000); ВыполнитьДинамически(10000); - выполняется Вообще я ожидал, что буду видеть процесс накапливания сообщений вида "Из процесса: Итерация №---" |
В всц 1.9 переделали терминал в сторону быстрого непосредственного вывода, но все равно такие вещи лучше тестировать прямо из консоли |
В консоли тоже самое (проверяю на 10000). Сначала висит, потом скопом выводит все строки |
исторически сложилось, что stdout - буферизированный вывод, то есть приложение не обязано выдавать его сразу (да и выдавать вообще - в случае падения). Потому "вжух и сразу 10000" - это обычное дело. |
@JohnyDeath а вот формировать в памяти построчную строку из 100500 конкатенаций - это жестоко :) В таких случаях лучше сразу писать в файл через ЗаписьТекста, а не мучить выделятор памяти. |
Закрываю: Реализовал неблокирующее чтение из потоков процесса. Особенность (возможно Breaking change): Методы ЕстьДанные Прочитать и ПрочитатьСтроку возвращают результат немедленно, показывая "Срез" на момент вызова. Отсутствие данных не означает конца потока. Оно означает, что на момент вызова в потоке данных не было. Данные в потоке появляются "построчно". Т.е. не будет оборванных на середине строк. |
По поводу breaking change - вроде у нас в скриптах всегда идёт дополнительная проверка на Процесс.Завершен, так что не должно поломать что-либо |
А раньше было не так? |
Раньше блокировалось и ждало пока данные поступят. Сейчас моментально возвращает результат. Часто пустой. |
И по поводу Процесс.Завершен. Как только он завершен обязательно надо прочитать еще раз. Там хвост данных часто приезжает с задержкой уже после остановки процесса. Т.е. для длительного процесса цикл Пока Не Завершен () и потом еще раз Прочитать. Для короткого можно ждать щавершения и потом читать. |
@artbear - обрати внимание на сообщение @EvilBeaver |
@EvilBeaver Проверил поведение на последнем ночнике. Но когда в этом коде я вместо Если вернул Пока (закомментировано), баг остался :( Проверял варианты
Висим :( Посмотришь? PS предлагаю переоткрыть ишуз! |
@artbear сбрось сюда конечный вариант кода, который зависает. |
@EvilBeaver смотри TODO СтрокаЗапуска = "git add -A .";
Процесс = СоздатьПроцесс(СтрокаЗапуска, ".", Истина, Ложь);
Процесс.Запустить();
ПериодОпросаВМиллисекундах = 200;
сообщить(20);
Если ПериодОпросаВМиллисекундах <> 0 Тогда
Приостановить(ПериодОпросаВМиллисекундах);
КонецЕсли;
сообщить(30);
//Если НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные Тогда
Индекс = 0;
Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные Цикл
Индекс = Индекс + 1;
// Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные Цикл
Если ПериодОпросаВМиллисекундах <> 0 Тогда
Приостановить(ПериодОпросаВМиллисекундах);
КонецЕсли;
сообщить("40 - " + Индекс);
ОчереднаяСтрокаВывода = Процесс.ПотокВывода.Прочитать();
сообщить(50); // TODO сюда выполнение не доходит!!!!!
ОчереднаяСтрокаВывода = СтрЗаменить(ОчереднаяСтрокаВывода, Символы.ВК, "");
сообщить(60);
// Лог.Отладка("%2%1", ОчереднаяСтрокаВывода, Символы.ПС);
// сообщить(70);
// ЗаписьXML.ЗаписатьБезОбработки(ОчереднаяСтрокаВывода);
сообщить(80);
//КонецЕсли;
КонецЦикла;
сообщить(90); |
Для приложенного к шапке архива |
Итак, правильное решение - читать поток вывода и поток ошибок.
Правильный код: Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные ИЛИ Процесс.ПотокОшибок.ЕстьДанные Цикл
Если ПериодОпросаВМиллисекундах <> 0 Тогда
Приостановить(ПериодОпросаВМиллисекундах);
КонецЕсли;
сообщить(40);
ОчереднаяСтрокаВывода = Процесс.ПотокВывода.Прочитать();
ОчереднаяСтрокаОшибок = Процесс.ПотокОшибок.Прочитать();
Если Не ПустаяСтрока(ОчереднаяСтрокаВывода) Тогда
Сообщить(ОчереднаяСтрокаВывода, СтатусСообщения.Информация);
КонецЕсли;
Если Не ПустаяСтрока(ОчереднаяСтрокаОшибок) Тогда
Сообщить(ОчереднаяСтрокаОшибок, СтатусСообщения.Важное);
КонецЕсли;
сообщить(50);
сообщить(60);
// Лог.Отладка("%2%1", ОчереднаяСтрокаВывода, Символы.ПС);
// сообщить(70);
// ЗаписьXML.ЗаписатьБезОбработки(ОчереднаяСтрокаВывода);
сообщить(80);
КонецЦикла; |
+ Методы по управления кодировкой вывода для КомадногоФайла + Зависание исправлено согласно решению в EvilBeaver/OneScript#402 (comment)
Теперь эта магия :) запрятана в 1commands! Управляется методом |
Дока на пример правильной обработки цикла ожидания завершения процесса #402
В результате расследования зависаний гитсинка с новым 1commands artbear/1commands#14
я нарвался на ошибку движка :(
У меня есть тестовый гит-репо, в котором core.autocrlf = true (это сделано специально!!)
Запускаю тестовый скрипт для этого репо
Как видно из кода, до
Сообщить(50)
выполнение не доходит, т.к. скрипт зависает вместе с гитом!При этом при ручном запуске
git add -A .
выдает кучу сообщений по отличия CrLf для каждого файла и через небольшое время завершается успешно./cc @dmpas @EvilBeaver Помогите!!
Без вашей помощи никак.
Прикладываю тестовый архив. Там и файлы, и тест.скрипт, и батник для его запуска :)
process-bug.zip
The text was updated successfully, but these errors were encountered: