强制终止卡在某个阻塞函数上的C++线程

q43xntqr  于 2023-02-14  发布在  其他
关注(0)|答案(2)|浏览(306)

我有一个std::线程,它监听来自Linux内核的netlink事件,它有一个无限while循环和一个阻塞函数,阻塞函数会阻塞到下一个事件。我想在程序工作流中强制停止线程,当我不再需要它的时候。
以下是我目前的解决方案:

#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <thread>
#include <signal.h>

void thread_func() {
    while(true) {
        std::cout << "Processing events.." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(10)); // simulating a blocking function that blocks until next events
        std::cout << "Events received.." << std::endl;
    }
}

int main() {
    std::thread eventListener(thread_func);
    std::this_thread::sleep_for(std::chrono::seconds(3)); // doing some work in main thread
    pthread_cancel(eventListener.native_handle()); // I don't want the eventListener anymore
    eventListener.join();
    std::cout << "eventListener killed" << std::endl;
    return 0;
}

我的程序只能编译到Linux平台。
它是来自libnl的实际阻塞函数nl_recvmsgs_default(nl_sock * sock)

    • 问题**:

1.这是C++中正确的做法吗?还是我遗漏了一些小细节?
1.有没有其他更好的方法来实现这一目标?
1.如果我改变上面的代码,用pthread_kill而不是pthread_cancel来终止线程,那么我在输出中看不到打印的"eventListener killed",我不知道为什么?

    • 更新:**设置一个标志对我来说不起作用,因为我甚至不知道函数会被阻塞多久,如果我没有从内核接收到任何新事件,那么函数永远不会恢复,在这种情况下,我只需要在将标志设置为true后等待(直到下一次while循环对来自内核的新netlink事件的迭代)。
ulydmbyx

ulydmbyx1#

重新设计,使您的线程不使用阻塞操作。
Netlink是作为套接字I/O实现的,因此您可以使用nl_socket_set_nonblocking,然后使用pollselect等“可中断”I/O多路复用来等待活动。
添加一个简单的pipe,这样你的循环线程在netlink套接字和管道的 read 端都是输入复用的。当需要结束循环时,让其他线程关闭 write 端-read端将立即显示为可读(对于EOF),你的循环线程将知道它的工作已经完成。
您可以使用一个简单的多线程程序(例如,阻塞在stdin上的程序)而不是netlink套接字来原型化这种方法。

krcsximq

krcsximq2#

您可能希望为阻塞函数使用一个时间间隔,这样它将返回并再次检查循环条件,以查看是否需要继续侦听。然后,您可以使用一个标志将线程从循环中释放。

相关问题