Как стать автором
Обновить

Комментарии 18

ЗакрепленныеЗакреплённые комментарии

То, что вы описали, формально правильно с точки зрения стандартов C и POSIX. Разве что, вы не упомянули atomic_signal_fence(), которая становится крайне необходима при нетривиальной работе с сигналами и современными компиляторами.

Содержательно ваша статья правильна для асинхронных сигналов. Но для них более предпочтительным подходом является sigwait(2) или в крайнем случае pipe trick. При использовании блока сигнала и sig*wait(2), обработчики не нужны, как они по сути не нужны и при использовании pipe trick (точнее, тут будет тривиальный заведомо async signal safe обработчик).

А вот для синхронных сигналов, которые доставляются синхронно как результат исключения, и именно в нитку, которая исключение сгенерировала, все существенно по другому. Во-первых, обработчику известно состояние программы, потому что известно место, где произошло исключение. Во-вторых, в обработчике обычно можно пользоваться практически всеми сервисами runtime (если только мы не говорим об исключениях вследствие разрушения состояния).

Из синхронного обработчика можно выйти не только восстановлением прерванного контекста, но и средствами типа longjmp или раскруткой стека. При этом вы не попадете в среду, где можно будет безопасно пользоваться только async-signal safe функциями, это будет нормальный контекст исполнения.

Современные типичные пользователи синхронных исключений - это всевозможные managed runtimes, которые реализуют на них барьеры для сборщиков мусора, парковку ниток, отслеживание выполнения (редких) блоков кода и тд.

Кстати, забавно, что работа с сигналами не обеспечена в Rust stdlib. Лучшее из того, что я находил, signal-hook, выглядит неубедительно.

Хотел написать примерно то же самое.
Ещё можно добавить, что
1) Есть техника, когда обработка какого-то сигнала разрешается «окнами»; даже если он генерируется асинхронно, обрабатываться он может синхронно. Особенно это типично для event-driven обработок. Есть системные вызовы pselect(), ppoll(), epoll_pwait() для поддержки такого стиля. В этом случае тоже снижаются ограничения на async-signal-safe сигналы.
2) Можно через sigwait допускать обработку назначенным обработчиком, а можно просто получать номер сигнала и далее шедулить самому.
3) Теперь есть ещё и signalfd для Linux и EV_SIGNAL для BSD kqueue.
Не смотря на то, что статья важная и нужная, но это всё описано и разжовано в каждом учебнике разработки *nix. И мне казалось, что каждый, хоть как-то мало-мальски программирует под линукс знает об этом.
НЛО прилетело и опубликовало эту надпись здесь
Расскажите, что за проекты, где идёт разработка в юзерспейсе?
НЛО прилетело и опубликовало эту надпись здесь
Я просто не там ворочаюсь. Обычно меня зовут либо дрова разрабатывать, либо портировать линукс, либо с загрузчиками возится. А так, чтобы спокойно писать приложения в юзерспейсе не сталкивался.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо!

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

Часто использую только signal(), по этому тут же полез консультироваться у FreeBSD-шного man-а, где сказано:

This signal() facility is a simplified interface to the more general sigaction(2) facility.

Т.е., как миниму во FreeBSD библиотечная функция signal() это обертка к системному вызову sigaction().

Далее читаем мануал по sigaction():

Once a signal handler is installed, it normally remains installed until another sigaction() system call is made, or an execve(2) is performed. A signal-specific default action may be reset by setting sa_handler to SIG_DFL. The defaults are process termination, possibly with core dump; no action; stopping the process; or continuing the process.

Делаю заключение, что как минимум во FreeBSD засады с подменой обработчика на дефолтный нет.

Отлегло. Пошел спать дальше.

НЛО прилетело и опубликовало эту надпись здесь

Так зачем ломать то что хорошо работает? Другой вопрос почему в линукс не пошли по этому пути.

То, что вы описали, формально правильно с точки зрения стандартов C и POSIX. Разве что, вы не упомянули atomic_signal_fence(), которая становится крайне необходима при нетривиальной работе с сигналами и современными компиляторами.

Содержательно ваша статья правильна для асинхронных сигналов. Но для них более предпочтительным подходом является sigwait(2) или в крайнем случае pipe trick. При использовании блока сигнала и sig*wait(2), обработчики не нужны, как они по сути не нужны и при использовании pipe trick (точнее, тут будет тривиальный заведомо async signal safe обработчик).

А вот для синхронных сигналов, которые доставляются синхронно как результат исключения, и именно в нитку, которая исключение сгенерировала, все существенно по другому. Во-первых, обработчику известно состояние программы, потому что известно место, где произошло исключение. Во-вторых, в обработчике обычно можно пользоваться практически всеми сервисами runtime (если только мы не говорим об исключениях вследствие разрушения состояния).

Из синхронного обработчика можно выйти не только восстановлением прерванного контекста, но и средствами типа longjmp или раскруткой стека. При этом вы не попадете в среду, где можно будет безопасно пользоваться только async-signal safe функциями, это будет нормальный контекст исполнения.

Современные типичные пользователи синхронных исключений - это всевозможные managed runtimes, которые реализуют на них барьеры для сборщиков мусора, парковку ниток, отслеживание выполнения (редких) блоков кода и тд.

Кстати, забавно, что работа с сигналами не обеспечена в Rust stdlib. Лучшее из того, что я находил, signal-hook, выглядит неубедительно.

НЛО прилетело и опубликовало эту надпись здесь

Под pipe trick понимают запись из обработчика сигнала в канал, при этом или основной цикл делает select(2) на чтение из другого конца канала, или (реже, как вы сказали) выделенная нитка читает из канала. Выделенная нитка неудобна тем, что ее нужно все равно интегрировать в основной событийный цикл с select/poll/epoll/kqueue.

Наскольно я помню, в линуксах есть signalfd(2), возвращающий файловый дескриптор, который можно использовать с select/epoll для синхронного оповещения о поступлении асинхронного сигнала напрямую, без создания канала.

Хотел написать примерно то же самое.
Ещё можно добавить, что
1) Есть техника, когда обработка какого-то сигнала разрешается «окнами»; даже если он генерируется асинхронно, обрабатываться он может синхронно. Особенно это типично для event-driven обработок. Есть системные вызовы pselect(), ppoll(), epoll_pwait() для поддержки такого стиля. В этом случае тоже снижаются ограничения на async-signal-safe сигналы.
2) Можно через sigwait допускать обработку назначенным обработчиком, а можно просто получать номер сигнала и далее шедулить самому.
3) Теперь есть ещё и signalfd для Linux и EV_SIGNAL для BSD kqueue.
НЛО прилетело и опубликовало эту надпись здесь

в лучшем случае приведет просто к неправильному результату, а в худшем случае уронит всю программу в segmentation fault.

Наоборот, первое - это худший случай, а второе -- лучший :)

Сигналы иногда еще приводят к неожиданным эффектам в неочевидных местах. Например мне попадалась такая ситуация:

  1. Есть драйвер который обрабатывает прерывания от железа и шлет сигналы процессам подписчикам когда что-то происходит в железе.

  2. Процесс-подписчик работает в том числе и с i2c, в моем случае это был USB-I2C на чипе mcp2221.

В итоге иногда сигнал будит драйвер посреди транзакции и из за особенности драйвера транзакция фейлится. Но в драйвере есть retry поэтому снаружи (в userspace который инициирует i2c транзакции) ошибки не видно. Нашли когда мониторили ошибки i2c через Kernel trace. Исправили изменениями в драйвере.

я бы отнёс этот случай к


в идеале они должны вообще сводиться к установке переменной-флага, которая будет обрабатываться в основном цикле программы или в специально выделенном для этого потоке
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории