使用带有std :: thread和pipe

时间:2017-03-31 13:01:31

标签: c++ multithreading signals posix c++14

考虑一个由许多工作线程组成的并行程序。这些线程在某些文件描述符上有一个poll循环。程序应该运行直到ctrl-c被命中/进程收到SIGINT。该程序永远不应该被不必要地唤醒。

我设计了以下sigwaitstd::threadpipepthread_sigmask的组合。请注意,在实际应用程序中,有更多的文件描述符,因此我没有使用atomics来关闭线程。

#include <thread>
#include <iostream>
#include <cstdlib>
#include <csignal>

extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <poll.h>
}

int fds[2];

void thread_run() {
    struct pollfd pfd = {fds[0], POLLIN, 0};
    int ret = poll(&pfd, 1, -1);
    if (ret != 1) std::terminate();
    if (!pfd.revents & POLLIN) std::abort();
}

int main()
{
    int ret = pipe(fds);
    if (ret) std::abort();

    sigset_t ss;
    sigemptyset(&ss);
    sigaddset(&ss, SIGINT);

    ret = pthread_sigmask(SIG_BLOCK, &ss, NULL);
    if (ret) std::abort();

    std::thread t(thread_run);

    int sig;
    ret = sigwait(&ss, &sig);
    if (ret) std::abort();

    char b = 0;
    ret = write(fds[1], &b, 1);
    if (ret != 1) std::abort();

    t.join();

    close(fds[0]);
    close(fds[1]);
}

该程序似乎没有任何问题。

  1. 这种做法是否符合要求,还是我忽略了任何警告?
  2. 在常规操作中是否存在任何特定的错误情况 并且可以更优雅地处理?
  3. 如果我交换std::thread - 创建和pthread_sigmask,该计划是否仍然正确?

1 个答案:

答案 0 :(得分:1)

  1. 这是一种标准的推荐方法,效果很好。请参阅pthread_sigmask
  2. 中的示例部分
  3. 无法发现任何。
  4. 这不正确。大多数信号都是特定于进程的,这意味着它们会被传递到进程中不阻塞该信号的任何线程。因此,必须在所有线程中阻止该信号,而不是处理信号的线程。
  5. 您可能希望std::abort来电,以应对意外情况。当异常处理失败时,C ++运行时将调用std::terminate