SIGCHLD и fork + waitpid () в библиотеке

Я пишу библиотеку, которая использует fork() и exec() для запуска внешних программ. Код в моей библиотеке работает как отдельный поток. Поток библиотеки должен обратиться к waitpid() в разветвленном процессе, чтобы узнать код выхода дочернего процесса.

К сожалению, если приложение, использующее мою библиотеку, зарегистрирует обработчик сигнала для SIGCHLD, вызовы waitpid() вернутся с ошибкой ECHILD.

Как мне справиться с этим как с библиотекой с минимальным влиянием на приложение? По сути, я хочу, чтобы ребенок оставался зомби и мог контролировать, когда его пожнут.

Могу ли я оградить себя от действий приложения? Могу ли я каким-то образом перехватить обработчик сигнала и вернуть его после того, как мой waitpid будет готов?

Вы можете разветвить свой процесс собственный для обработки вашей собственной обработки процесса и заставить библиотеку взаимодействовать с автономным процессом через каналы или что-то подобное МПК. Затем вы также можете установить свои собственные обработчики сигналов, например, ваш собственный SIGCHLD вместо того, чтобы полагаться только на waitpid.

Some programmer dude 20.09.2018 22:30

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

Nominal Animal 20.09.2018 22:37

Это давняя проблема с моделью вилки / ожидания Unix, и я не уверен, что есть какие-то простые решения.

Barmar 20.09.2018 22:44

Да, кажется, действительно сложная проблема. Спасибо за ответы! Поскольку моя библиотека используется очень контролируемым набором пользователей с известной функциональностью, я просто хочу сказать: «НЕ регистрировать обработчики сигналов».

user2624119 20.09.2018 22:46

Насколько я понимаю, стандартная функция system() страдает той же проблемой.

Barmar 20.09.2018 22:57

Вместо того, чтобы говорить им не устанавливать обработчики сигналов, предоставьте и задокументируйте функцию, которую они должны вызывать в начале своего обработчика SIGCHLD, чтобы ваша библиотека была довольна, и позаботьтесь о том, чтобы эта функция была безопасной для сигналов. И надеюсь, что другие библиотеки, которые использует программа, сами не управляют своими процессами, а оставят это основной программе, как и ваша библиотека тоже должна была сделать ;-)

mosvy 21.09.2018 00:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
739
2

Ответы 2

Освобождение ресурсов, выделенных библиотекой, является ошибкой приложения. В принципе, это то же самое, как если бы приложение делало что-то вроде free(yourlib_create_context(...)), хотя, конечно, последствия менее серьезны. Нет причин пытаться поддерживать такого рода бессмысленное поведение приложения; просто документально подтвердите, что он недействителен.

Если вы хотите "защитить" от такого рода ошибок программирования, маска сигнализирует, а затем вызывает abort, если waitpid не работает с ECHLD. Это безоговорочно завершит процесс, и у заявителя не будет возможности его поймать.

Вы можете сделать так же, как system:

system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

Набросок может быть

pid_t pid;
sigset_t block, backup;

sigemptyset(&block);
sigaddset(&block, SIGCHLD);

sigprocmask(SIG_BLOCK, &block, &backup);

if ((pid = fork()) < 0) {
    // error handle
} else if (pid == 0) {    // child
    sigprocmask(SIG_SETMASK, &backup, NULL);

    // ...
} else {
    // waitpid

    sigprocmask(SIG_SETMASK, &backup, NULL);
}

// ...

Другие вопросы по теме