我在Linux中有一个多线程的程序.有一些记忆区域,我有兴趣看看它们是否在一定时间内写完.为此,我只给予那些内存页面的读访问权限,并为SIGSEGV安装信号处理程序.现在我的问题是,每个线程是否会为自己调用信号处理程序.假设线程1写入一些禁止的内存区域,它会执行信号处理程序吗?
我想知道是否有可能/建议的方法来捕获SIGSEGV多线程环境中的信号.我特别感兴趣的是SIGSEGV通过类似的东西来处理*((int *)0) = 0.
关于这个主题的一些阅读导致我signal()和sigaction(),它安装了一个信号处理程序.虽然在多线程环境中似乎都没有前途.然后我尝试了sigwaitinfo(),在一个线程中接收信号,事先pthread_sigmask()调用阻止其他线程上的信号.它SIGSEGV使用raise(),在线程内或者通过类似的方式发送到进程时,信号被引发的程度起作用kill -SIGSEGV; 然而,\*((int*)0) = 0仍然杀死了这个过程.我的测试程序如下
void block_signal()
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
sigprocmask(SIG_BLOCK, &set, NULL);
if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
fprintf(stderr, "pthread_sigmask failed\n");
exit(EXIT_FAILURE);
}
}
void *buggy_thread(void *param)
{
char *ptr = NULL;
block_signal();
printf("Thread %lu created\n", pthread_self());
// Sleep for some random time
{ ... }
printf("About to raise from %lu\n", pthread_self());
// …Run Code Online (Sandbox Code Playgroud) 我试图了解 Rust 中的堆栈溢出处理程序。recursive_stack()我编写了一次又一次声明一些局部变量的函数以耗尽堆栈空间。
extern crate nix;
use nix::sys::signal;
extern "C" fn handle_sigsegv(_: i32) {
//Do something here
}
fn main() {
let sig_action = signal::SigAction::new(
signal::SigHandler::Handler(handle_sigsegv),
signal::SaFlags::SA_NODEFER,
signal::SigSet::empty(),
);
unsafe {
signal::sigaction(signal::SIGSEGV, &sig_action);
}
println!("Before function");
recursive_stack();
println!("After function");
}
fn recursive_stack() {
let _array: [i64; 50] = [0; 50];
recursive_stack();
}
Run Code Online (Sandbox Code Playgroud)
我想捕获信号并执行我的信号处理程序。如果我注册信号处理程序,我会收到“分段错误(核心已转储)”消息。如果我不注册信号处理程序,则会收到堆栈溢出消息。
如果我将其注册为信号,则该信号处理程序工作正常SIGINT,但会给出奇怪的结果SIGSEGV。我缺少什么?
我在 Ubuntu 18.04 上运行这个程序。
有趣的是,这似乎是一个基本问题,但我找不到任何C语言的例子(在SO中,我发现只有Python,C#和C++).
关键是:作为一个Qt程序员,当我需要在不同的线程之间传输一些数据时,我会在那之间启动信号槽连接并使用该emit signal机制来完成工作.
但现在我在嵌入式Linux的C应用程序中工作,我需要做类似的工作,但我没有Qt的机制可用.问题是:我怎样才能使两个或多个线程在C中以类似于Qt信号和插槽的方式相互通信?
我知道共享数据的方法之一是全局变量,其变量受互斥锁保护.但即便如此,我可能无法以异步方式执行系统:我必须有一个循环,不断检查变量是否已更改.但是,如果我想在另一个完成一些工作之后执行某个线程的特定方法(因此,以异步方式),该怎么办?然后它似乎失败了.
注意:虽然我使用的是嵌入式Linux,因此,提及一些可以采用POSIX功能和其他"Linux相关方式"的选项会有所帮助,如果有更多的时间用于解决方案,对社区来说仍然会更好.不严格基于某个特定平台(如果可能的话).
我知道SIGSEGV当内核使用它报告内存访问冲突时不能忽略这一点。但是,如果我安装一个SIGSEGV不执行任何操作的信号处理程序,然后另一个进程使用kill该信号向我发送该信号,那么其行为是否与我使用“正常”信号(如 )相同SIGUSR1?
例.
如果我有一个指针,
int* p;
p = (int*)2; // just for test
*p = 3; // it will be crack, right?
Run Code Online (Sandbox Code Playgroud)
通常,值2的指针的访问将是破解.但实际上裂缝并非如此简单.指针的无效值可能来自运行时错误.我想在访问之前找到一种检查指针的方法.