У меня есть программа на C ++ с несколькими потоками. В начале основного потока (до того, как появятся какие-либо потоки) я блокирую SIGUSR1 с помощью sigprocmask. Затем я создаю два потока, один ждет SIGUSR1 с помощью sigwait, а другой отслеживает дескрипторы файлов с помощью epoll_wait. По какой-то причине, когда я посылаю SIGUSR1 в эту программу, он перехватывается epoll_wait, а не sigwait.
Версия Linux 4.9.165
Я пытался явно заблокировать SIGUSR1 перед вызовом epoll_wait, но это не решает проблему. Я также пытался использовать epoll_pwait напрямую.
// main thread
// ...
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
// ...
//thread 1
// ...
sigset_t sigset;
int sig;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
auto ret = sigwait(&sigset, &sig);
if (ret != 0)
{
std::cout << "sigwait failed\n";
}
// ...
//thread 2
static constexpr int MAX_EVENTS = 10;
struct epoll_event events[MAX_EVENTS];
int timeout = -1;
// ...
sigset_t oldset;
sigprocmask(SIG_SETMASK, NULL, &oldset);
std::cout << (sigismember(&oldset, SIGUSR1) ? "SIGUSR1 blocked " : "SIGUSR1 not blocked ") << "in epoll thread\n";
epoll_wait(epollFd.Get(), static_cast<struct epoll_event*>(events), MAX_EVENTS, timeout);
if (nfds < 0)
{
std::cout << "Epoll wait failed: " << strerror(errno) << '\n';
}
// ...
Это дает мне вывод "Ошибка ожидания Epoll: прерван системный вызов" и поток sigwait никогда не просыпается.
Я также вижу «SIGUSR1 заблокирован в потоке epoll», указывающий, что перед epoll_wait сигнал SIGUSR1 был заблокирован.
Насколько я понимаю, дочерние потоки должны наследовать маски сигналов своих родителей, что epoll_wait следует рассматривать как epoll_pwait с нулевой сигма-маской (и, следовательно, не изменять маску сигнала), и что сигнал должен передаваться только поток с разблокированным сигналом (являющийся тем, у которого есть сигвейт). Я не прав?