当进程收到信号时,线程会发生什么?

安东·扎哈罗夫(Anton Zakharov)

我是C语言的新手,所以问题可能很愚蠢。

我正在写套接字服务器,它操作从客户端发送的数据。获取连接后,它将创建将与请求配合使用的线程。

它还定义了信号处理程序。收到SIGUSR1时,它将调试信息打印到日志文件中。问题是:运行信号处理功能时线程将如何处理?

如果线程继续运行其作业,是否可以在调试处理程序运行时冻结它们?

我试图在手册页中找到pthreads(7)的答案,但此刻还不了解。抱歉,您可能会使用错误的术语。

莫希斯·雷迪(Mohith Reddy)

线程和信号的一些介绍(signal(7)

  • 信号处置按过程

信号的配置是每个进程的属性:在多线程应用程序中,特定信号的配置对于所有线程都是相同的。

  • 信号可以是过程控制或线程控制的

过程控制信号:过程控制信号是针对整个过程的信号(因此待定)。可以将过程控制的信号传递到当前未阻塞信号的任何一个线程。如果多个线程的信号畅通无阻,则内核选择一个任意线程来将信号传递到该线程。

线程定向信号:线程定向信号是针对特定线程的信号。该集合将由未决的过程控制信号集合和调用线程的未决信号集合的并集组成。

  • 异步和同步信号处理

您可以配置程序以告诉您如何处理信号。您可以忽略它们(很少会被忽略),注册一个信号处理程序,该信号处理程序将在收到特定信号时被调用(asynchronous),或者阻塞它以便稍后处理(synchronous)。

谈到你的情况,

“问题是:当信号处理功能运行时线程会发生什么?”

信号一次传递到配置为接收该信号的任何线程。异步处理信号的线程将停止正在执行的操作,并跳转到已配置的信号处理程序。其余线程中的执行流程不受影响。

如果线程继续运行其作业,是否可以在调试处理程序运行时冻结它们?

没有标准的方法可以做到这一点。您需要构建自己的机制来启用此功能。

为了进一步研究,需要对调试处理程序的执行位置有一定的了解。在每个线程中main()还是在特定线程中?

编辑

假定main()实现了日志记录功能,下面将尝试实现相同的基本最低要求。添加了注释,使您可以遍历代码并了解实现。

#define THREAD_MAX_COUNT 100

#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int debug;
sigset_t debug_mask;
pthread_t main_tid;

void* thread_func(void* th_data)
{
    /* .... */

    for ( ; ; ) {

        if (debug) {    // If debug procedure starts
            printf("Freezing %d\n", *((int*) th_data));

            pthread_kill(main_tid, SIGRTMIN);  // Notify the main thread about the thread's freeze.
            int signo;
            sigwait(&debug_mask, &signo);  // Wait till logging is done. main() will signal once it is done. 

            printf("Resuming %d\n", *((int*) th_data));
        }

        /* ... */
    }

    return NULL;
}

int main() {

    /* Block SIGINT SIGRTMIN*/

    sigset_t sigmask;
    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGINT);
    sigaddset(&sigmask, SIGRTMIN);

    pthread_sigmask(SIG_BLOCK, &sigmask, NULL);

    /* Set debug variables */

    debug = 0;
    sigemptyset(&debug_mask);
    sigaddset(&debug_mask, SIGRTMIN);
    main_tid = pthread_self();

    /* Get signalfd for SIGINT */

    int sigfd = signalfd(-1, &sigmask, 0);
    struct signalfd_siginfo sigbuf;

    /* Select variable initializations */

    fd_set rd_set, tr_set;
    FD_ZERO(&rd_set);
    FD_SET(sigfd, &rd_set);

    int td_count = 0;
    pthread_t tids[THREAD_MAX_COUNT];

    for ( ; ; ) {
        /* Wait for signal */
        tr_set = rd_set;

        select(sigfd + 1, &tr_set, NULL, NULL, NULL);

        if (FD_ISSET(sigfd, &tr_set)) {
            /* Read the pending signal */
            read(sigfd, &sigbuf, sizeof(sigbuf));

            /* Start logging */
            debug = 1;

            int signo;
            for (int count = 0; count < td_count; count++) {
                /* Wait for all threads to freeze */
                sigwait(&debug_mask, &signo);
            }

            printf("Logging...\n");
            sleep(3);

            /* End logging and resume threads */
            debug = 0;

            for (int count = 0; count < td_count; count++)
                pthread_kill(tids[count], SIGRTMIN);

            /* Note below code is for testing purpose; Creates new thread on each interruption */
            int* td_data = malloc(sizeof(int));
            *td_data = td_count;

            pthread_create(tids + td_count, NULL, thread_func, td_data);

            td_count++;
        }
    }

    return 0;
}

终端会议:

$ gcc SO.c -lpthread 
$ ./a.out 
^CLogging...
^CFreezing 0
Logging...
Resuming 0
^CFreezing 0
Freezing 1
Logging...
Resuming 0
Resuming 1
^CFreezing 0
Freezing 1
Freezing 2
Logging...
Resuming 1
Resuming 0
Resuming 2
^CFreezing 2
Freezing 3
Freezing 1
Freezing 0
Logging...
Resuming 1
Resuming 3
Resuming 2
Resuming 0
^CFreezing 1
Freezing 4
Freezing 3
Freezing 0
Freezing 2
Logging...
Resuming 1
Resuming 2
Resuming 0
Resuming 4
Resuming 3
^CFreezing 3
Freezing 0
Freezing 4
Freezing 2
Freezing 5
Freezing 1
Logging...
Resuming 0
Resuming 1
Resuming 2
Resuming 5
Resuming 3
Resuming 4
^\Quit (core dumped)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

进程结束时,内核级线程会发生什么?

当已经在信号处理程序中时接收到信号会发生什么?

当subprocess.call收到终止信号时会发生什么?

多线程程序创建新进程时会发生什么?

进程终止时共享内存区域会发生什么?

使用可调用对象时主线程会发生什么

当线程在等待wait()时被中断时会发生什么?

当main()退出时,分离线程会发生什么?

当主线程退出时协程会发生什么?

当非root用户向root用户的进程发送信号时会发生什么?

完全使用WebContainer线程池(WebSphere)并收到新请求时会发生什么?

当两个或多个线程或进程ftruncate(2)相同文件时会发生什么?

结束后在进程中启动的线程会发生什么情况

Java-子线程死于NPE时,父线程被杀死会发生什么?

线程分叉时会发生什么?

调用线程的interrupt()会发生什么?

线程引发异常时会发生什么?

如果ThreadPool线程死亡,会发生什么?

当线程“唤醒”某物时会发生什么

示踪收到SIGCONT时,为什么会发生SIGTRAP PTRACE_EVENT_STOP?

如果子进程在阅读时无法关闭写入管道,会发生什么情况?

在Python多处理中,当子进程完全存在时,stdout会发生什么?

当进程被杀死时,文件描述符会发生什么?

当线程在同步块内崩溃时,锁会发生什么情况?

同步调用异步函数时被调用者的线程会发生什么

在某个线程上调用Thread.interrupt()时,会发生什么?

从C中main返回时,正在运行的线程会发生什么情况?

dlclose时,共享库产生的线程会发生什么情况

当原始类超出范围时,线程会发生什么情况