Многопоточная C программа;как убить процессы, порожденные потоками? - PullRequest
4 голосов
/ 17 февраля 2010

Положение:

Я пишу программу на C, которая поддерживает несколько потоков. После завершения потока создается новый.

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

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

Сигналы блокируются во всех потоках, кроме, конечно, потока обработчика сигналов.

Aim:

Я хочу иметь возможность завершить программу, отправив SIGTERM. Это сработает, остановив основной поток, создав новые потоки, а также остановив запущенные процессы, созданные потоками.

Проблема:

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

Есть ли способ заставить порожденные процессы получать только сигналы, отправленные из основной программы, а не сигналы, отправленные в основную программу?

Ответы [ 2 ]

5 голосов
/ 17 февраля 2010

Создайте все дочерние процессы в новой группе процессов, затем отправьте сигнал группе.

Edit:

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

#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

pid_t pgid; /* process group to kill */

void terminator( int s ) /* signal handler */
{
    printf( "[%d:%d] received signal %d, exiting\n",
        getpid(), getpgrp(), s );
    exit( 1 );
}

int main() /* program entry */
{
    printf( "[%d:%d] before first fork\n",
        getpid(), getpgrp() );

    switch ( fork()) /* try with and without first fork */
    {
        case -1: err( 1, "fork" );
        case 0: break;
        default: exit( 0 );
    }

    if ( signal( SIGTERM, terminator ) == SIG_ERR )
        err( 1, "signal" );

    if ( setpgrp() < 0 ) err( 1, "setpgrp" );
    if (( pgid = getpgrp()) < 0 ) err( 1, "getpgrp" );

    printf( "[%d:%d -> %d] before second fork\n",
        getpid(), getpgrp(), pgid );

    switch ( fork())
    {
        case -1: err( 1, "fork" );
        case 0: /* child */
        {
            printf( "child [%d:%d]\n", getpid(), getpgrp());
            sleep( 20 );
            break;
        }
        default: /* parent */
        {
            printf( "parent [%d:%d]\n", getpid(), getpgrp());
            sleep( 5 );
            killpg( pgid, SIGTERM );
            sleep( 20 );
        }
    }

    printf( "[%d:%d] exiting\n", getpid(), getpgrp());
    exit( 1 );
}

0 голосов
/ 17 февраля 2010
  1. Создайте все дочерние процессы в новой группе процессов, затем отправьте сигнал группе. (спасибо Николай)
  2. Вести записи обо всех созданных процессах и использовать их для оповещения о них при необходимости.
...