Чтоб при убиении родительского процесса, гибли и дочерние

Тема в разделе "WASM.UNIX", создана пользователем Quantum, 9 июн 2007.

  1. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Не совсем стандартная, вроде, ситуация:
    Основной процесс порождает дочерний (системной функцией clone).
    Далее основной процесс занимается бесконечным циклом вывода графики.
    Дочерний процесс выполняет бесконечный цикл вывода аудио.
    По нажатию пользователем спец. клавиши основной процесс сигналит дочернему, чтоб тот совершил суицид, дожидается эффективного завершения дочернего процесса и сам тоже завершается. В общем, всё чудесно работает, НО...

    Попадаются некоторые глючные версии графической либы (в основном, на старых дистрибутивах), которые не позволяют нормально отслеживать команду завершения от пользователя. Короче, когда пользователь закрывает окно XLib, библиотека автоматически киляет основной процесс, а дочерний, естественно, продолжает работать. Я пробовал вешать signal на kill, но это сообщение приходит не всегда.

    Как можно сделать, чтобы родительский процесс перед аварийным завершением успел просигналить дочернему, чтобы тот тоже завершился? Как выяснилось, из дочернего процесса я не могу следить за состоянием родительского (или как-то всё-таки можно?).
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А если сделать процесс-надсмотрщик, который будет проверять наличие обоих процессов (родителя и дочернего) и при завершении одного из них прибивать другой?
    И тогда будет неважно, как был завершен родительский процесс - закрытием окна или спец.клавишей.
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Не совсем понял, а нельзя в родительском процессе обрабатывать сигналы ведущие к смерти процесса из их обработчиков посылать группе процессов SIG_KILL, например. Правда, насколько я помню, SIG_KILL отловить нельзя (хотя в мане BSD об этом ничего не сказано). + есть еще обработчики выхода atexit(3) из стандартной библиотеки. Правда, это не спасет программу от сигнала, т.к. в обработчике сигналов нельзя вызывать ф-ию exit(3)...
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    cresta
    Если не найдётся более простое решение... К слову, я уже пробовал хучить функции Xlib и патчить глючные версии библиотек, но код получается слишком громоздким, а желательно, чтобы исходник был максимально простым и понятным даже для новичков.

    Mika0x65
    Именно это я и пытался реализовать в первую очередь. Посмотрел в отладчике, что родительскому процессу приходит сигнал KILL и решил отловить его через signal(). Как оказалось, KILL со стандартным кодом приходит не всегда. Кажется, иногда процесс самоприбивается через exit() где-то в недрах графических библиотек. Также пробовал ловить и другие сигналы - 100% срабатывания обработчика не получил.

    Попробую разобраться.
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    c qt получается очень просто и изящно :) Тем более, там есть все необходимые сигналы и слоты:

    Код (Text):
    1.     void Dlg::startProcesses(){
    2.         QProcess *  pProc = new QProcess (this);      // parent process
    3.         QProcess *  cProc = new QProcess (this);      // child process  
    4.          
    5.         // start parent process
    6.         pProc->addArgument("xboard");
    7.         pProc->start();
    8.        
    9.         // start child process        
    10.         cProc->addArgument("ksocrat");
    11.         cProc->start();
    12.        
    13.         // try terminate child if parent exited
    14.         connect( pProc, SIGNAL( processExited() ),
    15.                 cProc, SLOT(tryTerminate() ) );
    16.        
    17.         // try terminate parent if child exited        
    18.         connect( cProc, SIGNAL( processExited() ),
    19.                 pProc, SLOT( tryTerminate () ) );
    20.        
    21.     }
    На примере шахмат и словаря: при завершении любого из них второй тоже завершается. Пробовал и закрывать непосредственно окна и посылать SIGKILL процессам.
     
  6. Icegenerator

    Icegenerator New Member

    Публикаций:
    0
    Регистрация:
    6 май 2007
    Сообщения:
    5
    Quantum
    Нее, хучить это все грязные хаки. Заимплементь менеджер процессов твоих. Можно даже стандартно - модель, основанная на сообщениях.
     
  7. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    cresta
    Нечто подобное я и попробую завтра реализовать, только без Qt и на диалекте бейсика, если не получится с atexit.

    Всем спасибо за участие!
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Получилось! atexit() оказался недостающим звеном. Вопрос исчерпан.
     
  9. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Меня терзают некоторые сомнения. Поясню:

    Функция exit() вызывает обработчики atexit. exit() не может быть вызвана из обработчика сигнала (не реентранта, в списке разрешенных отсутствует). Соответственно, если придет сигнал, обработчики могут быть не вызваны. Вы потестили программу на вариант смерти от сигнала?
     
  10. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Mika0x65
    Есть 2 варианта:
    1. Окно закрывается юзером (клик по кнопке с крестиком). Соединение с сервером XWindow рвётся. Генерируется сигнал, по которому процесс прибивается. Это событие я обрабатываю: посылаю сигнал дочернему процессу, чтоб он тоже закрылся.
    2. Окно закрываетя по нажатию Esc. Тут никакие сигналы не генерируются, а просто выполняется exit() где-то в недрах рантайма компилятора. atexit() в этом случае оказался в самую пору.

    В общем, код теперь выглядит так (если переписать на C):

    Код (Text):
    1. int cleanup = 0;
    2. void onexit(){
    3.    if(!cleanup){
    4.       // do cleanup
    5.    }
    6. }
    7.  
    8. void main(){
    9.    // create child process
    10.    // ...
    11.    signal(XXXX, &onexit);
    12.    atexit(&onexit);
    13.    while(!kbhit()){
    14.       // do GFX
    15.    }
    16.    onexit();
    17.    cleanup = 1;
    18. }
    Все ресурсы теперь благополучно вычищаются как при нормальном, так и при аварийном завершении родительского процесса.