Не совсем стандартная, вроде, ситуация: Основной процесс порождает дочерний (системной функцией clone). Далее основной процесс занимается бесконечным циклом вывода графики. Дочерний процесс выполняет бесконечный цикл вывода аудио. По нажатию пользователем спец. клавиши основной процесс сигналит дочернему, чтоб тот совершил суицид, дожидается эффективного завершения дочернего процесса и сам тоже завершается. В общем, всё чудесно работает, НО... Попадаются некоторые глючные версии графической либы (в основном, на старых дистрибутивах), которые не позволяют нормально отслеживать команду завершения от пользователя. Короче, когда пользователь закрывает окно XLib, библиотека автоматически киляет основной процесс, а дочерний, естественно, продолжает работать. Я пробовал вешать signal на kill, но это сообщение приходит не всегда. Как можно сделать, чтобы родительский процесс перед аварийным завершением успел просигналить дочернему, чтобы тот тоже завершился? Как выяснилось, из дочернего процесса я не могу следить за состоянием родительского (или как-то всё-таки можно?).
А если сделать процесс-надсмотрщик, который будет проверять наличие обоих процессов (родителя и дочернего) и при завершении одного из них прибивать другой? И тогда будет неважно, как был завершен родительский процесс - закрытием окна или спец.клавишей.
Не совсем понял, а нельзя в родительском процессе обрабатывать сигналы ведущие к смерти процесса из их обработчиков посылать группе процессов SIG_KILL, например. Правда, насколько я помню, SIG_KILL отловить нельзя (хотя в мане BSD об этом ничего не сказано). + есть еще обработчики выхода atexit(3) из стандартной библиотеки. Правда, это не спасет программу от сигнала, т.к. в обработчике сигналов нельзя вызывать ф-ию exit(3)...
cresta Если не найдётся более простое решение... К слову, я уже пробовал хучить функции Xlib и патчить глючные версии библиотек, но код получается слишком громоздким, а желательно, чтобы исходник был максимально простым и понятным даже для новичков. Mika0x65 Именно это я и пытался реализовать в первую очередь. Посмотрел в отладчике, что родительскому процессу приходит сигнал KILL и решил отловить его через signal(). Как оказалось, KILL со стандартным кодом приходит не всегда. Кажется, иногда процесс самоприбивается через exit() где-то в недрах графических библиотек. Также пробовал ловить и другие сигналы - 100% срабатывания обработчика не получил. Попробую разобраться.
c qt получается очень просто и изящно Тем более, там есть все необходимые сигналы и слоты: Код (Text): void Dlg::startProcesses(){ QProcess * pProc = new QProcess (this); // parent process QProcess * cProc = new QProcess (this); // child process // start parent process pProc->addArgument("xboard"); pProc->start(); // start child process cProc->addArgument("ksocrat"); cProc->start(); // try terminate child if parent exited connect( pProc, SIGNAL( processExited() ), cProc, SLOT(tryTerminate() ) ); // try terminate parent if child exited connect( cProc, SIGNAL( processExited() ), pProc, SLOT( tryTerminate () ) ); } На примере шахмат и словаря: при завершении любого из них второй тоже завершается. Пробовал и закрывать непосредственно окна и посылать SIGKILL процессам.
Quantum Нее, хучить это все грязные хаки. Заимплементь менеджер процессов твоих. Можно даже стандартно - модель, основанная на сообщениях.
cresta Нечто подобное я и попробую завтра реализовать, только без Qt и на диалекте бейсика, если не получится с atexit. Всем спасибо за участие!
Меня терзают некоторые сомнения. Поясню: Функция exit() вызывает обработчики atexit. exit() не может быть вызвана из обработчика сигнала (не реентранта, в списке разрешенных отсутствует). Соответственно, если придет сигнал, обработчики могут быть не вызваны. Вы потестили программу на вариант смерти от сигнала?
Mika0x65 Есть 2 варианта: 1. Окно закрывается юзером (клик по кнопке с крестиком). Соединение с сервером XWindow рвётся. Генерируется сигнал, по которому процесс прибивается. Это событие я обрабатываю: посылаю сигнал дочернему процессу, чтоб он тоже закрылся. 2. Окно закрываетя по нажатию Esc. Тут никакие сигналы не генерируются, а просто выполняется exit() где-то в недрах рантайма компилятора. atexit() в этом случае оказался в самую пору. В общем, код теперь выглядит так (если переписать на C): Код (Text): int cleanup = 0; void onexit(){ if(!cleanup){ // do cleanup } } void main(){ // create child process // ... signal(XXXX, &onexit); atexit(&onexit); while(!kbhit()){ // do GFX } onexit(); cleanup = 1; } Все ресурсы теперь благополучно вычищаются как при нормальном, так и при аварийном завершении родительского процесса.