Skip to content
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

Попытка не перехватывает вложенное исключение в фоновом методе #1495

Open
tormozit opened this issue Jan 18, 2025 · 40 comments

Comments

@tormozit
Copy link

tormozit commented Jan 18, 2025

Версия ОСкрипт 1.9 (внутри Турбоконфа)
Выполняю фоново метод и выбрасываю в нем исключение и в попытке вывожу сообщение или любое другое сигнальное действие. Но сообщение (сигнал) не выводится и отладчик в секции "Исключение" не останавливается.

ФоновыеЗадания.Выполнить(ЭтотОбъект, "тест");

Процедура Тест() Экспорт
    Сообщить("Контроль1");
    Попытка
		ВызватьИсключение 23;
	Исключение
		Сообщить("Ошибка");
	КонецПопытки;
КонецПроцедуры

Этот тест выводит сообщение "Контроль1", но не "Ошибка".
Делаю вывод, что там что то сломано. Если будешь чинить, то большая просьба продублировать фикс в ветке 1.9

@tormozit
Copy link
Author

@bolsun на всякий случай уведомляю тебя. Вдруг Турбоконф тут как то причастен.

@sfaqer
Copy link
Contributor

sfaqer commented Jan 18, 2025

Image

В актуальных 1.9 и 2.0 не воспроизводится.
Можно закрывать

@tormozit
Copy link
Author

@sfaqer поясни, зачем ты добавил ОжидатьЗавершения(). У меня выполнение без синхронизации потоков.

@sfaqer
Copy link
Contributor

sfaqer commented Jan 18, 2025

@sfaqer поясни, зачем ты добавил ОжидатьЗавершения(). У меня выполнение без синхронизации потоков.

Потому что без ожидания потока основной поток (и всё приложение) завершается раньше чем завершится фоновый поток, и ты получишь то поведение что описал, это не ошибка это так работает

@tormozit
Copy link
Author

получишь то поведение что описал

Ты можешь это доказать проверкой моего теста?

@sfaqer
Copy link
Contributor

sfaqer commented Jan 18, 2025

получишь то поведение что описал

Ты можешь это доказать проверкой моего теста?

Image

Только в таком виде, без дополнительно сообщить или ещё какого нибудь кода после запуска ФЗ у меня поток завершается быстрее чем фоновый поток успевает начать работать, соответственно ничего не выведется вообще

@tormozit
Copy link
Author

tormozit commented Jan 18, 2025

Спасибо. Это немного проливает свет на происходящее. Но в моем случае материнский процесс (Турбоконф) создает объект ОСкрипт и запускает в нем скрипт. Внутри выполнения скрипта запускается фоновый метод. Основной метод (поток) скрипта быстро завершается. Но объект ОСкрипт с выполняющимся фоновым методом продолжает жить и завершается только при завершении фонового метода. Вот проблема в том, что любое исключение, выброшенное в таком фоновом методе, уходит в никуда, т.е. не перехватывается попыткой.

Видимо без разработчика Турбоконфа @bolsun не удастся до конца разобраться. Но пока я все же допускаю, что обработка исключения в этом сценарии выполняется некорректно в самом ОСкрипт.

@nixel2007
Copy link
Collaborator

А можно ожидать завершения фз в основном потоке, запускаемым турбоконфом? Или это мешает процессу/логике работы турбоконфа?

@tormozit
Copy link
Author

ожидать завершения фз в основном потоке

На минуту заморозить интерфейс Турбоконфа? Это будет жестоко.

@tormozit
Copy link
Author

tormozit commented Jan 18, 2025

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

@nixel2007
Copy link
Collaborator

На минуту заморозить интерфейс Турбоконфа? Это будет жестоко.

Я не знаю архитектуру турбоконфа, поэтому и спросил. Может там запуск оскрипта асинхронный, поэтому блокировки интерфейса бы не было.

@EvilBeaver
Copy link
Owner

Закрываю, т.к. турбоконф-specific

@bolsun
Copy link

bolsun commented Jan 20, 2025

Закрываю, т.к. турбоконф-specific

ТурбоКонф специфик или HostedScriptEngine специфик?

@bolsun
Copy link

bolsun commented Jan 20, 2025

Я не знаю как реализованы ФоновыеЗадания в OScript, но если взять по аналогии BackgroundWorker, то при возникновении исключения при его выполнении, оно тоже не будет вызвано в родительском процессе. Но для этого есть обработчик завершения выполнения, а в нем есть свойство Error. В котором содержится ошибка, если она была.

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }

@bolsun
Copy link

bolsun commented Jan 20, 2025

Таким образом IHostApplication вполне может иметь метод или событие, которое вызывается при ошибке в фоновомзадании.

@bolsun
Copy link

bolsun commented Jan 20, 2025

Поэтому может рановато закрывать?

@EvilBeaver
Copy link
Owner

IHostApplication имеет метод для отображения инфы об ошибке неперехваченного исключения, но не уверен, что он вызывается менеджером ФЗ и вообще такой кейс с ФЗ кажется надо проектировать отдельно.

Поэтому может рановато закрывать?

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

@tormozit
Copy link
Author

Актуально

@bolsun
Copy link

bolsun commented Jan 29, 2025

IHostApplication имеет метод для отображения инфы об ошибке неперехваченного исключения, но не уверен, что он вызывается менеджером ФЗ и вообще такой кейс с ФЗ кажется надо проектировать отдельно.

Я использую метод ShowExceptionInfo(Exception exc);

Но он не вызывается при исключении в фоновом задании.

@tormozit
Copy link
Author

tormozit commented Feb 1, 2025

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

Поэтому снова призываю всех, кто еще не проверил на своей стороне все возможности решить эту проблему, сделать это.

@bolsun
Copy link

bolsun commented Feb 2, 2025

Решил сам воспроизвести проблему и у меня все работает нормально.

Процедура ТестФЗ() Экспорт
	Сообщить("ТестФЗ");

	Попытка
		ВызватьИсключение "Исключение!";
	Исключение
		Сообщить("Исключение! " + ОписаниеОшибки());
	КонецПопытки;
КонецПроцедуры

Процедура ВыполнитьФоновоеЗадание() Экспорт
	ФЗ = ФоновыеЗадания.Выполнить(ЭтотОбъект, "ТестФЗ");
	ФЗ.ОжидатьЗавершения();
КонецПроцедуры

Image

@bolsun
Copy link

bolsun commented Feb 2, 2025

Получается, что OScript пробрасывает исключение в HostApplication, а TurboConf также корректно это обрабатывает.
Значит проблема либо в RDT.os либо в COMCoeдинении, либо в чем-то еще.

@bolsun
Copy link

bolsun commented Feb 2, 2025

Удалось выяснить, что если в внутри метода перехватывать исключение через Попытка Исключение КонецПопытки, то его можно обработать.
Если этой конструкции нет, то исключение все таки не пробрасывается дальше в HostApplication.

Такой код уже не работает корректно

Процедура ТестФЗ() Экспорт
	Сообщить("ТестФЗ");

	ВызватьИсключение "Исключение!";
	
КонецПроцедуры

Процедура ВыполнитьФоновоеЗадание() Экспорт
	ФЗ = ФоновыеЗадания.Выполнить(ЭтотОбъект, "ТестФЗ");
		ФЗ.ОжидатьЗавершения();
КонецПроцедуры

@tormozit
Copy link
Author

tormozit commented Feb 2, 2025

@bolsun выше #1495 (comment) уже разобрали что мне ФЗ.ОжидатьЗавершения() нельзя вызывать

@bolsun
Copy link

bolsun commented Feb 2, 2025

уже разобрали что мне ФЗ.ОжидатьЗавершения() нельзя вызывать

Это не при чем. В моем примере я использую ОжидатьЗавершения() и исключение обрабатывается.

@bolsun
Copy link

bolsun commented Feb 2, 2025

Вот без ожидания завершения.

Процедура ТестФЗ() Экспорт
	Сообщить("ТестФЗ");

	Попытка
		ВызватьИсключение "Исключение!";
	Исключение
		Сообщить("Исключение! " + ОписаниеОшибки());
		ТурбоКонф.ПоказатьВсплывающееУведомление("Ошибка", "Исключение! " + ОписаниеОшибки(), 6000);
	КонецПопытки;

КонецПроцедуры

Процедура ВыполнитьФоновоеЗадание() Экспорт
	ФЗ = ФоновыеЗадания.Выполнить(ЭтотОбъект, "ТестФЗ");
	//ФЗ.ОжидатьЗавершения();
КонецПроцедуры

Image

@tormozit
Copy link
Author

tormozit commented Feb 2, 2025

Да. В таком чистом тесте не воспроизводится. Сделаю полный тест.

@tormozit
Copy link
Author

tormozit commented Feb 2, 2025

Этот скрипт в среде Турбконф выводит сообщение "Ау1" и не выводит "Ау2" и не выбрасывает исключение. Входной метод - ЗапуститьПодключениеИР.

//@script_hotkey None            ЗапуститьПодключениеИР Тест

Функция ПодключениеИР() Экспорт
	Попытка
		Попытка
			ВызватьИсключение 1;
		Исключение
			Сообщить("Ау1");
		КонецПопытки;
		ВызватьИсключение 2;
	Исключение
		Сообщить("Ау2");
		ВызватьИсключение 3;
	КонецПопытки;
КонецФункции

Процедура ЗапуститьПодключениеИР()
	ФоновыеЗадания.Выполнить(ЭтотОбъект, "ПодключениеИР");
КонецПроцедуры

@bolsun
Copy link

bolsun commented Feb 2, 2025

Этот скрипт в среде Турбконф выводит сообщение "Ау1" и не выводит "Ау2" и не выбрасывает исключение. Входной метод - ЗапуститьПодключениеИР.

Дело даже не в пробрасывании исключения или текста ошибки в HostApplication.
Похоже в ФоновомЗадании код после перехвата вложенного исключения, дальше не выполняется совсем.
Скорее всего будет даже воспроизводится даже в чистом тесте без TurboConf (не пробовал).

Функция ПодключениеИР() Экспорт
	Попытка
		Попытка
			ВызватьИсключение 1;
		Исключение
			Сообщить("Ау1");
			 //ЗапуститьПриложение("calc.exe"); //здесь работает
		КонецПопытки;
		
		//ЗапуститьПриложение("calc.exe"); // Здесь работает

		ВызватьИсключение 2;
	Исключение
		ЗапуститьПриложение("calc.exe"); // Здесь не работает
	КонецПопытки;
	
	ЗапуститьПриложение("calc.exe"); // Здесь не работает
КонецФункции

@tormozit tormozit changed the title Попытка не перехватывает исключение в фоновом методе Попытка не перехватывает вложенное исключение в фоновом методе Feb 2, 2025
@tormozit
Copy link
Author

tormozit commented Feb 2, 2025

@EvilBeaver пора переоткрывать заявку

@EvilBeaver
Copy link
Owner

@EvilBeaver пора переоткрывать заявку

Тест от @bolsun воспроизводится в ванильном оскрипте?

@tormozit
Copy link
Author

tormozit commented Feb 2, 2025

@EvilBeaver вот тест для чистого ОСкрипт 1.9

Функция ПодключениеИР() Экспорт
	Попытка
		Попытка
			ВызватьИсключение 1;
		Исключение
			Сообщить("Ау1");
		КонецПопытки;
		ВызватьИсключение 2;
	Исключение
		Сообщить("Ау2");
		ВызватьИсключение 3;
	КонецПопытки;
КонецФункции

Ф = ФоновыеЗадания.Выполнить(ЭтотОбъект, "ПодключениеИР");
ф.ОжидатьЗавершения();

Результат подтвержден. Выводит сообщение "Ау1" и не выводит "Ау2" и не выбрасывает исключение. Похоже есть ошибка в управлении попытками в фоновом режиме выполнения кода.

Image

@nixel2007
Copy link
Collaborator

Cc @sfaqer

@sfaqer
Copy link
Contributor

sfaqer commented Feb 2, 2025

Дело в общем вообще не связано с фоновым заданием, исключение из внешней попытки не будет перехвачено если есть вложенная попытка.
Завёл отдельный ишью с описанием проблемы: #1498
Так же закинул тесты на это поведение: #1497

@tormozit
Copy link
Author

tormozit commented Feb 3, 2025

@sfaqer однако поведение без фонового задания другое

Функция ПодключениеИР() Экспорт
	Попытка
		Попытка
			ВызватьИсключение 1;
		Исключение
			Сообщить("Ау1");
		КонецПопытки;
		ВызватьИсключение 2;
	Исключение
		Сообщить("Ау2");
		ВызватьИсключение 3;
	КонецПопытки;
КонецФункции
ПодключениеИР();

Image

Значит тут двойная ошибка в ОСкрипт.

@sfaqer
Copy link
Contributor

sfaqer commented Feb 3, 2025

Нет тут другого поведения, фоновое задание не выбрасывает исключение by design у фонового задания есть свойство ИнформацияОбОшибке, в котором лежит информация о исключении возникшем внутри фонового задания.
Поэтому ты не видишь исключения в логе при запуске через фоновое задание, ты его просто не выводишь

@tormozit
Copy link
Author

tormozit commented Feb 3, 2025

@sfaqer Согласен.

@tormozit
Copy link
Author

tormozit commented Feb 3, 2025

Как гарантировать донесение необработанного в фоновом задании исключения до пользователя/журнала в случае, когда основная программа завершила работу (нет ожидания)?
Может добавить в метод ФоновыеЗадания.Выполнить() параметр для проброса исключения наружу в виде сообщения?

@EvilBeaver
Copy link
Owner

Переоткрываю, т.к. требует проектирования API исключений в ФЗ

@EvilBeaver EvilBeaver reopened this Feb 3, 2025
@nixel2007
Copy link
Collaborator

ФоновыеЗадания.Выполнить() параметр для проброса исключения наружу в виде сообщения?

Куда наружу, если основной поток по твоим словам завершился?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants