通过信号中断睡眠
Interrupt sleep by signal
我想编写一个 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);
}
有人知道如何解决这个问题吗?
程序returns在执行信号处理程序后正常运行。睡眠不会终止,因为它与处理信号的线程处于不同的线程中,如评论中的 stark 注释。
相反,这个答案 suggests using a mutex to block operation. This is made easier with 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
带着ti7和user4581301的思路终于找到了解决方法
在 signal_handler 中使用互斥锁的想法但仅限于允许的系统调用集,我使用信号量。
sem_t *sem_g = nullptr;
extern "C" void handler(int s) {
if (sem_g)
sem_post(sem_g);
}
int main() {
sem_t sem = {};
sem_init(&sem, 0, 0);
sem_g = &sem;
std::signal(SIGUSR1, handler);
auto f = std::async(std::launch::async, [&] {
auto start = std::chrono::high_resolution_clock::now();
auto time_point = std::chrono::system_clock::now() + 10s;
auto duration = time_point.time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration);
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - secs);
timespec t{secs.count(), nanos.count()};
auto r = sem_timedwait(&sem, &t);
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++ 程序,它应该等待 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);
}
有人知道如何解决这个问题吗?
程序returns在执行信号处理程序后正常运行。睡眠不会终止,因为它与处理信号的线程处于不同的线程中,如评论中的 stark 注释。
相反,这个答案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
带着ti7和user4581301的思路终于找到了解决方法
在 signal_handler 中使用互斥锁的想法但仅限于允许的系统调用集,我使用信号量。
sem_t *sem_g = nullptr;
extern "C" void handler(int s) {
if (sem_g)
sem_post(sem_g);
}
int main() {
sem_t sem = {};
sem_init(&sem, 0, 0);
sem_g = &sem;
std::signal(SIGUSR1, handler);
auto f = std::async(std::launch::async, [&] {
auto start = std::chrono::high_resolution_clock::now();
auto time_point = std::chrono::system_clock::now() + 10s;
auto duration = time_point.time_since_epoch();
auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration);
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - secs);
timespec t{secs.count(), nanos.count()};
auto r = sem_timedwait(&sem, &t);
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);
}