Дочерний процесс получает СИГИНТ родителя

Дочерний процесс получает СИГИНТ родителя

24.07.2011 01:23:19 Просмотров 33 Источник

У меня есть одна простая программа, которая использует Qt Framework. Он использует QProcess для выполнения RAR и сжатия некоторых файлов. В моей программе я ловлю SIGINTи делаю что-то в своем коде, когда это происходит:

signal(SIGINT, &unix_handler);

Когда SIGINT, который был предназначен для моей программы, и он завершает работу, прежде чем сжал все файлы.

Есть ли способ запустить процесс RAR так, чтобы он не получал SIGINT, когда моя программа получает его?

Спасибо

У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint#comment8080637_6803395
В настоящее время я тестирую его на Debian 5.0.8

Ответы - Дочерний процесс получает СИГИНТ родителя / Child process receives parent's SIGINT

Arnold Spence

24.07.2011 04:10:12

Что ты делаешь в своем кураторе? Существуют только определенные функции Qt, которые можно безопасно вызывать из обработчика сигналов unix. Эта страница в документации определяет, какие они.

Основная проблема заключается в том, что обработчик будет выполняться вне основного потока событий Qt. Эта страница также предлагает метод, чтобы справиться с этим. Я предпочитаю, чтобы обработчик "отправил" пользовательское событие в приложение и обработал его таким образом. Я опубликовал ответ, описывающий, как реализовать пользовательские события здесь .

https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804114#comment8080650_6804114
Спасибо за эту страницу, Я не знал об этом. Я просто вызываю quit и жду своих потоков, а затем выхожу из приложения. Это работает для всех, кроме RAR, так что я не думаю, что это проблема. Но я прочту эту страницу. Спасибо снова
Является ответом!
Nemo

24.07.2011 04:18:06

Если вы генерируете SIGINTс помощью Ctrl + C в системе Unix, то сигнал передается всей группе процессов .

Вы должны использовать setpgid или setsid, чтобы поместить дочерний процесс в другую группу процессов, чтобы он не получал сигналы, генерируемые управляющим терминалом.


[Редактировать:]

Обязательно внимательно прочитайте раздел обоснование на странице setpgid. Это немного сложно, чтобы подключить все потенциальные условия гонки здесь.

Чтобы гарантировать 100%, что никакой SIGINTне будет доставлен в ваш дочерний процесс, вам нужно сделать что-то вроде этого:

SIGINT

Строго говоря, каждый из этих шагов необходим. Вы должны заблокировать сигнал в случае, если пользователь нажмет Ctrl + C сразу после вызова #define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ } /* Block SIGINT. */ sigset_t mask, omask; sigemptyset(&mask); sigaddset(&mask, SIGINT); CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0); /* Spawn child. */ pid_t child_pid = fork(); CHECK(child_pid >= 0); if (child_pid == 0) { /* Child */ CHECK(setpgid(0, 0) == 0); execl(...); abort(); } /* Parent */ if (setpgid(child_pid, child_pid) < 0 && errno != EACCES) abort(); /* or whatever */ /* Unblock SIGINT */ CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0); . Вы должны вызвать forkв дочернем случаеsetpgidпроизойдет до того, как родитель успеет что-либо сделать. Вы должны вызвать forkв родителе в случае, если родитель работает и кто-то нажимает Ctrl + C, прежде чем ребенок успевает что-либо сделать.

Последовательность выше неуклюжа, но она действительно обрабатывает 100% условий гонки.

https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment8080662_6804155
Большое спасибо. Я думаю, что это ответ на мою проблему. Я постараюсь сделать это как можно скорее ;)
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment8080761_6804155
Это работает, я просто добавил правильный include и эту строку: setpgid(rar.pid (), 0);
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment8083874_6804155
Без проблем. Обратите внимание, что setpgidчреват условиями гонки, и его правильное использование немного деликатно. Я обновил свой ответ, чтобы быть более полным.
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment8087995_6804155
Спасибо за дополнительную информацию ;)
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment10147302_6804155
опечатка в последнем случае. EACCES и не EACCESS
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment11079309_6804155
@NaN: спасибо; исправлено (наконец-то)
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19555757_6804155
Это использование assertкрайне неправильно! assertусловно включен или отключен, а когда отключен, он полностью устраняет свой аргумент. Вы должны использовать if(1!...) abort()или ваш собственный макрос, обертывающий его.
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19555901_6804155
@Jan - /* or whatever */подразумевало "какова бы ни была ваша политика обработки ошибок". Является ли это использование assert"неправильным", полностью зависит от этой политики. (Там, где я работаю, мы никогда не компилируем с NDEBUG, поэтому assertможно использовать для случаев "этого никогда не должно произойти".)
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19556105_6804155
@Nemo: "/ * или что-то еще * / " было правильным. Но важных звонковassertбумагу, не было. Так получилось, что в Linux вы обычно не контролируете, будет ли код компилироваться с NDEBUGили нет, так как довольно легко вызвать configure CPPFLAGS="-O3 -fomit-frame-pointer -DNDEBUG"
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19556122_6804155
@Jan - я не согласен с вашим редактированием,поэтому я вернул его. Ваши комментарии все еще здесь для любого, кто наткнется на это в будущем.
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19556349_6804155
@Jan: использование assertдля "невозможных" случаев совершенно нормально и совершенно правильно. (И вы заметите, что этот код использует assertдля таких невозможных случаев; fork, которая на самом деле может потерпеть неудачу, проверяется явно.) Ваше понижение основано на вашем личном мнении, а не на техническом факте или стандартной практике. Я добавил /* or whatever */к assert, чтобы сделать вас счастливыми,хотя это и не обязательно. Достаточно честно?
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19557192_6804155
@Nemo: да, но при условии, что: 1) выражение в аргументе assertне имеет побочных эффектов (нарушается здесь) и 2) условие может быть истинным только в том случае, если в программе есть ошибка (это не относится к результату setpgid).
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment19559216_6804155
@Jan: Ну, я не согласен с assert, что оно подходит для выражений ,которые "истинны только в том случае, если в вашей программе есть ошибка". В этом контексте setpgid(0,0)может завершиться ошибкой только в том случае, если имеется ошибка в библиотеке C или ядре, и проверка таких "невозможных" случаев с assertвполне разумна. Но у тебя есть хорошая идея насчет побочных эффектов. Я думалassert(x)гарантированно оценит x, но я ошибался. Я вернулся к вашей версии.
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment78395363_6804155
Не будет ли это проблематично, если ребенок каким-то образом имеет приоритет над родителем и зависает, потому что разблокировка сигналов выполняется только в родителе?
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment78486485_6804155
@Sarien: независимо от приоритетов, оба процесса гарантированно достигнут прогресса "в конечном счете". Нажатие Ctrl-C во время блокировки сигнала приведет к тому, что он будет помещен в очередь и доставлен, как только он будет "в конечном итоге" разблокирован.
https://stackoverflow.com/questions/6803395/child-process-receives-parents-sigint/6804155#comment78498183_6804155
@Nemo хорошо, но все же он может работать в течение длительного времени, не будучи в состоянии принимать сигналы, не так ли?
Закрыть X