首页 > 解决方案 > 通过信号中断睡眠

问题描述

我想编写一个 C++ 程序,它应该等待一个 linux 信号(毫秒分辨率),但我找不到实现这一点的可能性。

以下测试代码应在 500 毫秒后终止,但事实并非如此。

#include <iostream>
#include <csignal>
#include <unistd.h>
#include <chrono>
#include <future>

using namespace std::chrono_literals;

extern "C" void handler(int s) {

}

int main() {
    std::signal(SIGUSR1, handler);

    bool started = false;
    auto f = std::async(std::launch::async, [&] {
        auto start = std::chrono::high_resolution_clock::now();
        started = true;

        //usleep(1000000);
        sleep(1);
        //std::this_thread::sleep_for(1s);


        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::high_resolution_clock::now() - start).count() << "ms";

    });
    std::this_thread::sleep_for(500ms);
    std::raise(SIGUSR1);
}

有人知道如何解决这种行为吗?

标签: c++linuxc++17system-callsusleep

解决方案


执行您的信号处理程序后,程序将返回其正常操作。睡眠不会终止,因为它与处理信号的线程在不同的线程中作为注释中的明确注释。

相反,这个答案是 C/C++: How to exit sleep() when an interrupt到达?建议使用互斥锁来阻止操作。这更容易try_lock_for

还显示线程 ID(显示它们是不同的线程),这可能是:

#include <iostream>
#include <csignal>
#include <unistd.h>
#include <chrono>
#include <future>

using namespace std::chrono_literals;

std::timed_mutex mtx;

extern "C" void handler(int s) {
    std::cout << std::this_thread::get_id() << " signal handler"
        << std::endl;
    mtx.unlock();
}

int main() {
    std::signal(SIGUSR1, handler);
    auto start_outer = std::chrono::high_resolution_clock::now();

    mtx.lock();

    auto f = std::async(std::launch::async, [&] {
        auto start = std::chrono::high_resolution_clock::now();

        mtx.try_lock_for(std::chrono::milliseconds(1000));

        std::cout << std::this_thread::get_id() << " "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::high_resolution_clock::now() - start).count() << "ms"
            << std::endl;
    });

    std::this_thread::sleep_for(500ms);
    std::cout << std::this_thread::get_id() << " "
        << std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::high_resolution_clock::now() - start_outer).count() << "ms"
        << std::endl;
    std::raise(SIGUSR1);
}

构建、运行、输出

% g++ -std=c++17 test.cpp && ./a.out
0x112cb9dc0 506ms
0x112cb9dc0 signal handler
0x700009e86000 506ms

推荐阅读