Является ли SIGSEGV особенным, когда генерируется `kill`?

я знаю это SIGSEGV не может быть проигнорировано, когда ядро ​​использует это, чтобы сообщить о нарушении доступа к памяти. Но если я установлю обработчик сигнала для SIGSEGV это ничего не делает, а затем использует другой процесс kill чтобы послать мне этот сигнал, он будет вести себя так же, как если бы я использовал «нормальный» сигнал (например, SIGUSR1) вместо?

1

Решение

У меня есть функция, которая получает сигнал SIGSEGV но ничего с этим не делать, значит ли это, что сигнал игнорируется?

Да, вы поймали сигнал SIGSEGV и ничего не делаете в обработчике, управление возвращается.

Вообще игнорирование реального SIGSEGV не означает ошибку не будет включите программу для продолжения значимого выполнения. Примечание. SIGSEGV не является сигналом, отправляемым через пользовательские запросы (некоторая комбинация клавиш), SIGSEGV возникает, когда программа пытается читать или записывать данные вне памяти, выделенной для нее. Название является аббревиатурой от «нарушение сегментации».

SIG35-С. Не возвращаться из обработчика сигнала исключительной ситуации

Согласно стандарту C, подпункт 7.14.1.1. ISO / IEC
9899: 2011
, если обработчик сигнала введен в результате вычислительного
исключение (то есть со значением аргумента SIGFPE, SIGILL,
или SIGSEGV или любое другое определяемое реализацией значение, соответствующее
такое исключение) возвращает, поведение не определено.

Поведение процесса не определено после того, как он игнорирует SIGFPE,
SIGILL, SIGSEGV, или же SIGBUS сигнал, который не был сгенерирован
kill(), sigqueue(), или же raise()
.

второй

Сигнал проходит к реализации по умолчанию?

Нет, согласно стандартному поведению цитаты или ваш код не не определено при генерации сигнала kill(), Реализация по умолчанию немедленно убьет выполнение вашего процесса и сгенерирует дамп кода (ссылка: Стандартные сигналы).

Zack«s комментарий:

Ваш код имеет четко определенное поведение — сигнал будет получен,
обработчик будет работать, он ничего не будет делать, управление вернется в нормальное состояние
поток — но вы все равно должны изменить его, чтобы использовать какой-то другой сигнал.
SIGUSR1 а также SIGUSR2 предназначены для использования так, как вы используете
SIGSEGV прямо сейчас, как внутренние сообщения приложения к себе.

Библиотека GNU C — хороший ресурс для изучения Обработка сигналов.

2

Другие решения

Ответ Грижеша Чаухана технически верен, но труден для понимания, поэтому я собираюсь написать собственное изложение в основном тех же моментов. Со сносками.0

Дима спрашивает, что происходит, когда один поток устанавливает обработчик бездействия для SIGSEGV а затем другой поток использует kill1 чтобы генерировать SIGSEGV в этой теме. Ответ из одного предложения состоит в том, что обработчик выполняется, ничего не делает, а затем управление возвращается к нормальному потоку внутри прерванного потока. В отличие от того, когда ядро ​​генерирует SIGSEGV в качестве ответа на фактическое нарушение доступа к памяти, этот сценарий не спусковой крючок неопределенное поведение2. Тем не менее, предполагаемая цель SIGSEGV и его друзья (SIGBUS, SIGFPE, а также SIGILL) для ядра, чтобы сказать вашей программе, что она сделала что-то настолько отвратительное, что должен будь ошибкой, нормальное выполнение не может продолжаться, ты бы хотел немного почистить, прежде чем тебя убьют? Поэтому неразумно использовать их для чего-либо еще. Есть несколько сигналов (SIGUSR1, SIGUSR2, а также SIGRTMIN через SIGRTMAX) зарезервировано для каждого приложения для использования по своему усмотрению; Вы должны использовать один из них вместо этого.


Для более длинного ответа, я собираюсь шпаргалки из стандарта POSIX,3 подраздел Сигнальные действия. Во-первых, четыре сигнала SIGFPE, SIGILL, SIGSEGV, а также SIGBUSкак и любой другой сигнал, может быть доставлен «асинхронно» — без особого времени — потому что некоторый фрагмент кода использовал системный вызов (такой как kill) генерировать их. Когда это происходит, они обрабатываются точно так же, как и любой другой сигнал, чье «действие» по умолчанию оказывается «ненормальным завершением программы»; обратите внимание, что многие другие сигналы имеют это свойство, в том числе зарезервированные для использования в приложении. Если ваша программа только беспокоится о получении SIGFPE, SIGILL, SIGSEGV, а также SIGBUS когда они генерируются kill и друзья, он может делать с ними все обычные вещи: блокировать их, игнорировать их, устанавливать обработчики сигналов, которые делают все, что допустимо для асинхронного обработчика сигналов,4 получить их через sigwait или же signalfd а не нормальный ловушка асинхронной системы-как механизм доставки.

Тем не мение. SIGFPE, SIGILL, SIGSEGV, а также SIGBUS также генерируются «синхронно» ядром в ответ на различные виды ошибочного поведения программы, которые вызывают аппаратные исключения, такие как попытка доступа к не отображенной памяти. Синхронно означает, что сигнал доставлен немедленно после выполнения ошибочной инструкции ЦП и в том же потоке, а не в каком-либо потоке в процессе, который, как оказалось, разблокирован. И мы действительно не шутим о «немедленной» части: если есть обработчик сигнала, когда он выполняется, счетчик сохраненной программы будет указывать на точную инструкцию, которая вызвала какие бы то ни было аппаратные исключения. Ядро не может допустить, чтобы выполнение проходило через инструкцию, которая заставляет ЦП выдавать аппаратное исключение, поэтому POSIX говорит об этом, пытаясь отбросить эти сигналы, а не завершать процесс или предпринимать какие-то радикальные действия по восстановлению:

Поведение процесса не определено после того, как он игнорирует SIGFPE, SIGILL, SIGSEGV, или же SIGBUS сигнал, который не был сгенерирован kill(), sigqueue(), или же raise(),

(«После игнорирования» в контексте означает «если ядро ​​пытается генерировать один из этих сигналов синхронно, когда действие установлено на SIG_IGN.)

Поведение процесса не определено после того, как он нормально возвращается из функции перехвата сигнала для сигнала SIGBUS, SIGFPE, SIGILL или SIGSEGV, который не был сгенерирован kill (), sigqueue () или повышение ().

(«Возвращает нормально» означает «не по телефону (sig)longjmp«. Это является допустимо, по крайней мере, что касается ядра, разматывать стек и возобновлять выполнение где-то еще; вы можете столкнуться с проблемами, если вы не достаточно исправили поврежденную структуру данных, которая изначально вызвала ошибку. Также, как упомянул Бэйзил, также допустимо связываться с сохраненным состоянием процессора, так что возвращение «нормально» не просто пытается выполнить ту же самую плохую инструкцию снова; но делает тот имеет тенденцию включать ручную интерпретацию машинных инструкций и другую подобную чёрную магию.)

Если какой-либо из сигналов SIGFPE, SIGILL, SIGSEGV или SIGBUS генерируется во время их блокировки, результат не определен, если только сигнал не был сгенерирован действием другого процесса или одной из функций kill (), pthread_kill () , поднять () или sigqueue ().

(Я не уверен, почему эта формулировка немного отличается от двух других; возможно, только потому, что человек, который написал специальная документация для sigprocmask не согласовывать с человеком, который написал общая документация для сигнальных действий.)


0 Дима отметил их вопрос «Linux», но я все равно собираюсь добавить это предостережение для будущих читателей: все, что я здесь пишу, должно применяться только в POSIX-совместимые операционные системы; в первом порядке, это означает, что «все операционные системы, с которыми вы, вероятно, столкнетесь, кроме Windows». Исключение важно. В Windows представление об отношениях между потоками и процессами несколько иное, чем в POSIX, и полностью другой (превосходящий!) фундаментальный механизм сообщения об исключениях ошибочных программ, генерируемых ЦП. Сигналы в Windows эмулируются библиотекой C и, вероятно, не ведите себя так, как я описываю.
1 предположительно на самом деле pthread_kill.
2 пожалуйста прочтите это все серия постов в блоге
3 в частности, онлайн-копия Открытая группа базовых спецификаций, выпуск 7, выпуск 2013 г., который также «одновременно» выпущен в 2013 году в стандарте IEEE 1003.1, POSIX.
4 не много, но больше, чем ничего; есть список вСигнальные действияmsgstr «документ, но без идентификатора фрагмента, что позволяет мне указать вам прямо на это.

2

У меня есть функция, которая получает сигнал SIGSEGV, но ничего не делать с ним,
это означает, что сигнал игнорируется?

Технически это не игнорируется. Вы определили обработчик сигнала, и он обрабатывает сигнал, хотя функция ничего не делает.
Обратите внимание, что в отношении сигнала IGNORE означает, что ядро ​​не обрабатывает сигнал, то есть не предпринимает никаких действий.

Каждый сигнал имеет действие по умолчанию. Это coredump (оканчивается на core) для SEGV и оканчивается для SEGKILL и т.д …

Пользователь может изменить действие по умолчанию с помощью API signal () или sigaction (), и действие может быть настроено на одно из:

  1. выполнить действие по умолчанию
  2. игнорировать сигнал
  3. поймать сигнал с помощью обработчика сигнала

Так что в вашем случае это третий. Я бы сказал, игнорируя сигнал, если вы использовали второе действие.

Сигнал проходит к реализации по умолчанию?

Нет.

читать http://man7.org/linux/man-pages/man7/signal.7.html для большего.

0
По вопросам рекламы [email protected]