gpt4 book ai didi

c - C 中带有进程和 2 个线程的信号处理不起作用

转载 作者:太空狗 更新时间:2023-10-29 12:37:27 24 4
gpt4 key购买 nike

我正在使用以下示例(基于 linux 中 pthread_sigmask 联机帮助页中的示例):

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

/* Simple error handling functions */

#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void * silly_worker(void *arg)
{
for(int index=0,max=5; index<max; ++index) {
printf("waiting %d of %d\n",index,max);
sleep(1);
}
puts("Finished waiting. Here comes the SIGSEGV");
strcpy(NULL,"this will crash");
}

static void *
sig_thread(void *arg)
{
sigset_t *set = (sigset_t *) arg;
int s, sig;

for (;;) {
s = sigwait(set, &sig);
if (s != 0)
handle_error_en(s, "sigwait");
printf("Signal handling thread got signal %d\n", sig);
}
}

int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_t thread2;
sigset_t set;
int s;

/* Block SIGINT; other threads created by main() will inherit
a copy of the signal mask. */

sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGSEGV);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");

s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");

/* Main thread carries on to create other threads and/or do
other work */

s = pthread_create(&thread2, NULL, &silly_worker, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");

pause(); /* Dummy pause so we can test program */
}

根据手册页,这应该捕获由 silly_worker 线程生成的 SIGSEGV。但事实并非如此。事实上,我完全不确定是哪个机构收到了信号。当程序运行时,我得到以下输出:

waiting 0 of 5
waiting 1 of 5
waiting 2 of 5
waiting 3 of 5
waiting 4 of 5
Finished waiting. Here comes the SIGSEGV
Segmentation fault

您可以看到信号处理程序没有输出“Segmentation fault”字符串,因此它一定来自默认处理程序。如果默认,那么它有点破坏了示例的目的 - 设置信号处理程序并捕获信号并对它们执行某些操作。

我可以找到很多处理程序的示例,但没有一个适用于这种情况:它们都没有演示导致非常明显的 SIGSEGV 的线程,并在其自定义处理程序中捕获并报告错误。

问题仍然存在:如何获得自定义信号处理程序以从这个 SIGSEGV 线程获取信号?

最佳答案

来自无效内存访问的 SIGSEGV(与 killsigqueue 发送的“假”访问相对)被发送到线程执行无效内存访问,而不是整个过程。因此,您不能拥有专用的段错误处理程序线程。如果你想处理它,你必须在它发生的线程中处理它。 (你看到 shell 打印 Segmentation fault 的原因是,当 SIGSEGV 在线程中被阻塞并且发生段错误时,内核执行默认操作杀死过程。实际上它是每个 POSIX 的 UB,但这是 Linux 处理 UB 的方式。)

但是请注意,您可以让 SIGSEGV 的信号处理程序通过专用线程触发操作。一个丑陋的方法是使用另一个信号,您可以通过 sigqueue 发送(连同参数)。更简洁的方法(至少在我看来)是让 SIGSEGV 处理程序使用 sem_post,它是异步信号安全的,可用于唤醒另一个等待信号量的线程。

关于c - C 中带有进程和 2 个线程的信号处理不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7368113/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com