首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIGPIPE的σ处理

SIGPIPE的σ处理
EN

Stack Overflow用户
提问于 2021-02-22 13:03:15
回答 2查看 77关注 0票数 1

当一个进程的输出被管道输送到另一个进程时,我试图实现它的优雅关闭。我正在测试下面的代码,它的输出是:./a.out | less,并在出现提示符时按下q。我看到的不是sigwait()的预期完成,而是信号处理程序的调用(这里添加它只是为了显示正在发生的事情)。

代码语言:javascript
复制
#include <csignal>
#include <chrono>
#include <iostream>
#include <thread>

#include <signal.h>

int handlerSig {0};

void signalHandler(int s)
{
    handlerSig = s;
    std::cerr << "handlerSig: "  << handlerSig << std::endl;
}

int main()
{
    for (int i = 1; i < 32; ++i)
    {
        std::signal(i, signalHandler);
    }

    bool run {true};
    std::thread thread {[&]
        {
            while (run)
            {
                std::cout << "ping" << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds {500});        
            }
        }};

    sigset_t waitSet;
    sigemptyset(&waitSet);
    sigaddset(&waitSet, SIGINT);
    sigaddset(&waitSet, SIGPIPE);
    sigaddset(&waitSet, SIGTERM);

    pthread_sigmask(SIG_BLOCK, &waitSet, nullptr);

    int waitSig {0};
    sigwait(&waitSet, &waitSig);
    run = false;
    thread.join();

    std::cerr << "waitSig: "  << waitSig << std::endl;
}

我在WSL2和CentOS机器上得到了一致的结果,我更愿意集中精力解决这个问题。在WSL1下运行时,除非我删除pthread_sigmask(SIG_BLOCK...),否则SIGINT或SIGTERM都不会导致sigwait()的完成,但这似乎与我对如何使用sigwait()的理解相矛盾。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-22 15:15:08

您需要想出其他方法来注意写入失败,例如,忽略SIGPIPE但设置std::cout.exceptions(ios::badbit),或者在写入线程中处理信号。

重要的是,SIGPIPE将始终为您的写入线程生成,尽管您的sigwait()正在执行线程。从线程的活动中产生的某些信号只为该线程生成,这意味着它们将仅被传递到该线程或被该线程接受。(POSIX.1-2008 2.4.1)通常,“自然发生”的SIGPIPE、SIGFPEs和SIGSEGV都是这样工作的。

票数 1
EN

Stack Overflow用户

发布于 2021-02-22 16:32:57

这是将SIGPIPE转发到主线程的一个示例--在我的情况下可能就足够了:

代码语言:javascript
复制
#include <csignal>
#include <chrono>
#include <iostream>
#include <thread>

#include <signal.h>

pthread_t mainThread {pthread_self()};

void forwardSig(int sig)
{
    if (not pthread_equal(pthread_self(), mainThread))
    {
        pthread_kill(mainThread, sig);
    }
}

int main()
{
    struct sigaction newAction {};
    sigemptyset(&newAction.sa_mask);
    newAction.sa_handler = forwardSig;
    sigaction(SIGPIPE, &newAction, nullptr);

    bool run {true};
    std::thread thread {[&]
        {
            while (run)
            {
                std::cout << "ping" << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds {500});        
            }
        }};

    sigset_t waitSet;
    sigemptyset(&waitSet);
    sigaddset(&waitSet, SIGINT);
    sigaddset(&waitSet, SIGPIPE);
    sigaddset(&waitSet, SIGTERM);

    pthread_sigmask(SIG_BLOCK, &waitSet, nullptr);

    int waitSig {0};
    sigwait(&waitSet, &waitSig);
    run = false;
    thread.join();

    std::cerr << "waitSig: "  << waitSig << std::endl;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66316244

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档