gpt4 book ai didi

c++ - 如何中止对 sigwaitinfo 的调用?

转载 作者:太空宇宙 更新时间:2023-11-04 12:03:02 26 4
gpt4 key购买 nike

背景

我的目标是在专用线程上处理某些信号,而不是在发出信号时让它们在恰好在我的进程中运行的任何线程上处理。

我按如下方式执行此操作(在此示例中,仅针对信号 16):

在主线程上,在任何其他线程启动之前(省略错误处理)

sigset_t sigset;
sigaddset(&sigset, 16);
sigprocmask(SIG_BLOCK, &sigset, nullptr);

然后我创建一个等待这些信号的线程(在这个例子中只有 16 个):

std::thread _thread = std::thread([&]()
{
int ret = sigwaitinfo(&sigset, nullptr);
if (ret == 16)
{
// handle signal 16
}
});

这很有效。

问题

但是,我希望能够在需要时取消对 sigwaitinfo 的调用。

两个不充分的解决方案

我尝试了两种解决方案,但都不够:

1。轮询

一个选项(可行)是不使用 sigwaitinfo,而是使用接受超时参数的 sigtimedwait。这允许我使用轮询并在下次调用返回并且设置了一些取消标志时取消。线程中的代码如下所示:

std::atomic<bool> _cancel (false);
std::thread _thread = std::thread([&]()
{
timespec _timespec {0, 1}; // 1 second
int ret = sigtimedwait(&sigset, nullptr, _timespec);
if (_cancel)
{
return;
}
if (ret == 16)
{
// handle signal 16
}
});

为了取消,我只需要在主线程中设置_cancel标志。此解决方案的问题在于,轮询会导致(取消的)响应性和检查取消标志的繁忙工作量之间的典型权衡。

2。 raise()/sigqueue()/kill()

在这个解决方案中,我向信号掩码添加了一个专用信号,例如 SIGUSR1,调用如下:

sigset_t sigset;
sigaddset(&sigset, 16);
sigaddset(&sigset, SIGUSR1); // <-- added call here
sigprocmask(SIG_BLOCK, &sigset, nullptr);

然后当我需要取消对 sigwaitinfo 的调用时,我设置一个取消标志并调用 raise(SIGUSR1)

线程中的代码如下所示:

std::atomic<bool> _cancel (false);
std::thread _thread = std::thread([&]()
{
int ret = sigwaitinfo(&sigset, nullptr);
if (_cancel) // <-- now check _cancel flag before handling signal
{
return;
}
if (ret == 16)
{
// handle signal 16
}
});

取消现在完成如下:

_cancel = true; // <-- set the flag before raising the signal
raise(SIGUSR1);

这个解决方案的问题是它不起作用,因为对 raise() 的调用不会导致 sigwaitinfo 在专用线程中返回。我相信根据文档,它只会在执行线程本身中引发信号。sigqueue() 和 kill() 也不起作用。

总结

有没有一种方法可以使 sigwaitinfo 过早返回,而不需要一个在超时时调用 sigtimedwait 的循环?

最佳答案

使用pthread_kill向特定线程发送信号。

例如,代替 raise(SIGUSR1); 做:

if(int rc = ::pthread_kill(_thread.native_handle(), SIGUSR1))
// Handle pthread_kill error.

关于c++ - 如何中止对 sigwaitinfo 的调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51687753/

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