我正在ROS环境下工作,并尝试在并行线程上读取CANBUS。我在主线程中初始化了 canbus,因为我想确保 CAN 电缆已连接。通过初始化,我的意思是 setsockopt()
、ioctl()
、bind()
来配置套接字。
void readCanbus(int soktId) {
while(true)
int nbytes = read(soktId, ...);
}
int main() {
int soktId;
someSocketSetupFn(soktId);
std::thread t(readCanbus, soktId);
t.join();
}
问题:如果没有传入 CAN 消息,则 read()
被阻止。 Ctrl+C 不会终止 C++11 程序。
如何使 read()
终止并终止整个程序?
Terminate thread c++11 blocked on read 这篇文章提出了 POSIX 的解决方案。我正在 ubuntu16.04 上工作。
最佳答案
如果您想模仿其他线程上的中断行为,这些线程必须允许中断,并且您的信号处理线程必须将信号传递给它们。考虑以下代码片段:
static volatile std::atomic<bool> quit;
static volatile std::deque<std::thread> all;
static volatile pthread_t main_thread;
void sigint_handler (int) {
if (pthread_self() == main_thread) {
write(2, "\rQuitting.\n", 11);
quit = true;
for (auto &t : all) pthread_kill(t.native_handle(), SIGINT);
} else if (!quit) pthread_kill(main_thread, SIGINT);
}
退出是通过设置全局变量来传达的。线程将唤醒并检查该变量。唤醒线程就是访问该线程并向其发送信号。
如果工作线程在主线程之前拦截到 SIGINT
,则会将其发送到主线程以启动正确的关闭序列。
为了允许被中断,线程可以调用siginterrupt()
。
void readCanbus(int s) {
siginterrupt(SIGINT, 1);
while(!quit) {
char buf[256];
int nbytes = read(s, buf, sizeof(buf));
}
write(2, "Quit.\n", 6);
}
我们定义了两种安装信号处理程序的方法,一种使用 signal
,另一种使用 sigaction
,但使用提供类似于 signal< 的语义的标志
.
template <decltype(signal)>
void sighandler(int sig, sighandler_t handler) {
signal(sig, handler);
}
template <decltype(sigaction)>
void sighandler(int sig, sighandler_t handler) {
struct sigaction sa = {};
sa.sa_handler = handler;
sa.sa_flags = SA_RESTART;
sigaction(sig, &sa, NULL);
}
主线程安装信号处理程序,初始化main_thread
,并使用稍后需要关闭的工作线程填充容器。
int main () {
int sp[2];
main_thread = pthread_self();
socketpair(AF_UNIX, SOCK_STREAM, 0, sp);
all.push_back(std::thread(readCanbus, sp[0]));
sighandler<sigaction>(SIGINT, sigint_handler);
for (auto &t : all) t.join();
}
关于c++ - 如果 I/O read() 处于阻塞阶段,如何使用 Ctrl+C 退出 C++ 程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59413344/