Что происходит, когда поток вызывает longjmp () в c - PullRequest
1 голос
/ 07 июня 2019

Что происходит, когда у вас есть поток, который вызывает longjmp на языке c. Я знаю, что когда программа находится в одном потоке, PC помещается обратно на адрес, когда был создан jmp_buf, и регистры процессора восстанавливаются к этому моменту времени.

  1. Если внутри потока вызывается setjmp, а затем вызывается longjmp, все может быть в порядке?
  2. Что если setjmp вызывается до того, как какие-либо потоки существуют, а затем поток вызывает longjmp для этого jmp_buf, уничтожает ли он все остальные потоки, поскольку они не существовали, когда был создан jmp_buf?

Ответы [ 2 ]

4 голосов
/ 07 июня 2019

Спецификацию POSIX для соответствующих функций можно найти по адресу:

Обратите внимание, что в спецификации для longjmp() перечислены некоторые ограничения:

Функция longjmp() должна восстановить среду, сохраненную последним вызовом setjmp() в том же процессе, с соответствующим аргументом jmp_buf. Если самый последний вызов setjmp() с соответствующим jmp_buf произошел в другом потоке, или если такого вызова нет, или если функция, содержащая вызов setjmp(), прекратила выполнение в промежуточный период, или если вызов из setjmp() находился в области действия идентификатора с изменяемым типом, и выполнение оставило эту область в промежуточном состоянии, поведение не определено. [CX] is Не указано, восстанавливает ли longjmp () маску сигнала, оставляет маску сигнала неизменной или восстанавливает ее значение до значения, которое было вызвано setjmp (). ⌫

Для ваших сценариев:

  1. Должно быть в порядке.
  2. Неопределенное поведение. Если вместо этого основной поток (или поток, вызвавший setjmp()) выполняет longjmp(), он должен быть в порядке, но он не будет уничтожать другие потоки. Скорее всего, вы нарушите общие ограничения на longjmp().

В целом, будь благоразумным и очень консервативным. Это хрупкие функции. Не используйте их, если в этом нет особой необходимости, и беспокойтесь об управлении ресурсами в целом.

3 голосов
/ 07 июня 2019

Я хочу, чтобы языковой адвокат сказал наверняка, но я подозреваю, что это приведет к неопределенному поведению, если вы попытаетесь longjmp() из потока в jmp_buf, созданный другим потоком.

Моя причина в том, что два потока обычно имеют совершенно разные стеки, и, по крайней мере, на MSVC x64 setjmp() сохраняет rbp и rsp, которые являются указателями на текущий стек. Конечным результатом этого является то, что поток, который вызывает longjmp(), выйдет из setjmp() с указателем стека и указателем кадра, указывающим на середину стека другого потока.

На планете Земля нет никакого способа, которым эта ситуация может хорошо закончиться.

...