Информация об изменениях

Сообщение Re: Исключение в другом потоке от 19.08.2025 19:03

Изменено 19.08.2025 19:09 watchmaker

Re: Исключение в другом потоке
Здравствуйте, T4r4sB, Вы писали:

TB>Суть такова, до какого-то обновления (вот не помню, какую версию gcc я использовал) при возникновении исключения внутри потока, созданного через std::async, программа падала (я его нигде не перехватывал), причём срабатывал обработчик какого-то сигнала , который выводил трассу стека (при старте приложения вызывалась такая функция https://llvm.org/doxygen/namespacellvm_1_1sys.html#ab062fd190912d9ca714311df7cbe51d5).

TB>После обновления то ли компилятора, то ли фреймворка (сорян за сумбур, уже не могу откатиться и перепроверить) исключения в другом потоке стали молча глотаться.

Ни падение программы, ни проглатывание исключения не является валидным поведением для std::async.
На самом деле исключение, вылетевшее из вызываемой функции, сохраняется в future (и его можно потом перевыбросить при вызове get-метода).

Скорее всего, ты что-то путаешь, и либо раньше использовал другие примитивы (например, явно thread и сам выставлял promise), либо твоя программа падала не из-за исключения, а, скажем, из-за связанного SIGSEGV. В обоих случаях обработчики terminate, сигналов или отдадчики вполне могут выдавать stacktrace.

TB>Как сделать чтоб "было как раньше"? Чтоб исключение в другом потоке сразу вызывало падение с правильной трассой.

Вспоминай, что использовал до этого :)
Потому что вызов std::async служит, чтобы выполнить функцию и получить её исключение и результат. Если это не подходит, то нужно не использовать async.


TB> Причём я пробовал их перехватить и перебросить (например вызвать .get у фьючи, которую вернул std::async), но проблема в том, что при этом я теряю трассу: выводится позиция не того места, где на самом деле возникло исключение, а позиция того места, где я его перебросил.


Тут тоже не понятно, на что ты смотришь. Одно дело, если ты видел statcktrace из terminate после неудачной раскрутки, а другое дело, если ты хочешь в объекте исключения хранить ассоциированный с ним путь и инспектировать его в программе...

Технически возможно собирать полный путь раскрутки и сохранять его в объекте исключения. Но дорого. Например, есть неприятные случаи, связанные тем, что сохранённое в exception_ptr исключение может быть перевыброшено несколько раз, и в памяти стектрейсы представляют собой дерево, а не список. И желательно не тормозить.

Впрочем, это решаемые проблемы, и хотя предложение P2370 Stacktrace from exception стагнирует, у него есть пара реализаций, которые в большинстве случаев включают запись пути через границы exception_ptr/future.
Re: Исключение в другом потоке
Здравствуйте, T4r4sB, Вы писали:

TB>Суть такова, до какого-то обновления (вот не помню, какую версию gcc я использовал) при возникновении исключения внутри потока, созданного через std::async, программа падала (я его нигде не перехватывал), причём срабатывал обработчик какого-то сигнала , который выводил трассу стека (при старте приложения вызывалась такая функция https://llvm.org/doxygen/namespacellvm_1_1sys.html#ab062fd190912d9ca714311df7cbe51d5).

TB>После обновления то ли компилятора, то ли фреймворка (сорян за сумбур, уже не могу откатиться и перепроверить) исключения в другом потоке стали молча глотаться.

Ни падение программы, ни проглатывание исключения не является валидным поведением для std::async.
На самом деле исключение, вылетевшее из вызываемой функции, сохраняется в future (и его можно потом перевыбросить при вызове get-метода).

Скорее всего, ты что-то путаешь, и либо раньше использовал другие примитивы (например, явно сам запускал thread и выставлял promise), либо твоя программа падала не из-за исключения, а, скажем, из-за связанного SIGSEGV. В обоих случаях обработчики terminate, сигналов или отдадчики вполне могут выдавать stacktrace.

TB>Как сделать чтоб "было как раньше"? Чтоб исключение в другом потоке сразу вызывало падение с правильной трассой.

Вспоминай, что использовал до этого :)
Потому что вызов std::async служит, чтобы выполнить функцию и получить её исключение и результат. Если это не подходит, то нужно не использовать async.


TB> Причём я пробовал их перехватить и перебросить (например вызвать .get у фьючи, которую вернул std::async), но проблема в том, что при этом я теряю трассу: выводится позиция не того места, где на самом деле возникло исключение, а позиция того места, где я его перебросил.


Тут тоже не понятно, на что ты смотришь. Одно дело, если ты видел statcktrace из terminate после неудачной раскрутки, а другое дело, если ты хочешь в объекте исключения хранить ассоциированный с ним путь и инспектировать его в программе...

Технически возможно собирать полный путь раскрутки и сохранять его в объекте исключения. Но дорого. Например, есть неприятные случаи, связанные тем, что сохранённое в exception_ptr исключение может быть перевыброшено несколько раз, и в памяти стектрейсы представляют собой дерево, а не список. И желательно не тормозить.

Впрочем, это решаемые проблемы, и хотя предложение P2370 Stacktrace from exception стагнирует, у него есть пара реализаций, которые в большинстве случаев включают запись пути через границы exception_ptr/future.