cam*_*ccc 6 c multithreading signals longjmp
我有一个大型程序,需要尽可能具有弹性,并具有大量的线程.我需要捕获所有信号SIGBUS SIGSEGV,并在必要时重新初始化问题线程,或禁用线程继续减少功能.
我的第一个想法是做一个setjump,然后设置信号处理程序,可以记录问题,然后longjump回到线程中的恢复点.有一个问题是信号处理程序需要确定信号来自哪个线程,使用适当的跳转缓冲区作为跳回到错误的线程将是无用的.
有没有人知道如何确定信号处理程序中的违规线程?
在我的 Linux 机器上使用syscall(SYS_gettid)对我有用:gcc pt.c -lpthread -Wall -Wextra
//pt.c
#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <ucontext.h>
#include <stdlib.h>
static sigjmp_buf jmpbuf[65536];
static void handler(int sig, siginfo_t *siginfo, void *context)
{
//ucontext_t *ucontext = context;
pid_t tid = syscall(SYS_gettid);
printf("Thread %d in handler, signal %d\n", tid, sig);
siglongjmp(jmpbuf[tid], 1);
}
static void *threadfunc(void *data)
{
int index, segvindex = *(int *)data;
pid_t tid = syscall(SYS_gettid);
for(index = 0; index < 500; index++) {
if (sigsetjmp(jmpbuf[tid], 1) == 1) {
printf("Recovery of thread %d\n", tid);
continue;
}
printf("Thread %d, index %d\n", tid, index);
if (index % 5 == segvindex) {
printf("%zu\n", strlen((char *)2)); // SIGSEGV
}
pthread_yield();
}
return NULL;
}
int main(void)
{
pthread_t thread1, thread2, thread3;
int segvindex1 = rand() % 5;
int segvindex2 = rand() % 5;
int segvindex3 = rand() % 5;
struct sigaction sact;
memset(&sact, 0, sizeof sact);
sact.sa_sigaction = handler;
sact.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sact, NULL) < 0) {
perror("sigaction");
return 1;
}
pthread_create(&thread1, NULL, &threadfunc, (void *) &segvindex1);
pthread_create(&thread2, NULL, &threadfunc, (void *) &segvindex2);
pthread_create(&thread3, NULL, &threadfunc, (void *) &segvindex3);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为了更加便携pthread_self可以使用。它是异步信号安全的。
但是获得 a 的线程SIGSEGV应该通过异步信号安全的方式启动一个新线程,并且不应该执行 a ,siglongjmp因为它可能导致调用非异步信号安全函数。
| 归档时间: |
|
| 查看次数: |
626 次 |
| 最近记录: |