【问题标题】:Multithreaded C program; how to kill processes spawned by threads?多线程C程序;如何杀死线程产生的进程?
【发布时间】:2010-02-17 14:59:48
【问题描述】:

情况:

我正在用 C 语言编写一个维护多个线程的程序。一旦线程结束,就会创建一个新线程。

每个线程分叉 - 子进程通过 exec() 运行一个进程,父进程等待它完成。

此外,还有一个等待信号的信号处理线程。如果检测到 SIGINT,它会告诉主线程停止创建线程,以便最终所有线程都结束并且程序可以退出。

信号在所有线程中都被阻塞,当然信号处理线程除外。

目标:

我希望能够通过发送 SIGTERM 来终止程序。这将通过停止创建新线程的主线程并终止由线程创建的正在运行的进程来工作。

问题:

如果信号在所有线程中都被阻塞,我如何向正在运行的进程发送信号以终止它们?

有没有办法让衍生的进程只接收主程序发送的信号而不接收发送给主程序的信号?

【问题讨论】:

    标签: c multithreading fork signals


    【解决方案1】:

    在一个新的进程组中创建所有子进程,然后向该组发送信号。

    编辑:

    这里有一些最小的代码,展示了进程如何通过信号改变它的组和控制子进程。

    #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 );
    }
    
    

    【讨论】:

    • 这正是我所做的,但它似乎无法正常工作。我使用的组 ID 是主线程的 PID - 对吗?
    • 假设 kill(),您是否将信号发送到组 id 的 negative?你也可以使用 killpg().
    • 是的,主进程调用这个(pgrp是全局的):pgrp = getpid(); setpgid(0,0);然后在每个线程中创建子进程:setpgid(0,pgrp);我尝试杀死这样的进程:killpg(pgrp, SIGTERM);
    • 好的,我看到调用进程的 groupID 和它的 PID 一样,我用它作为子进程的 groupID,这就是信号永远不会到达的原因。有什么建议可以解决这个问题吗?
    • 不要在子进程中调用 setpgid(0,pgrp); - 进程组 id 已被继承。
    【解决方案2】:
    1. 在一个新进程组中创建所有子进程,然后向该组发送信号。 (感谢 Nokolai)
    2. 保留所有已创建进程的记录,并在需要时使用这些记录向它们发出信号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 2011-02-13
      • 2017-11-11
      • 1970-01-01
      • 2023-04-06
      相关资源
      最近更新 更多