Libev C++ 无法停止多线程应用程序中的动态循环

Posted

技术标签:

【中文标题】Libev C++ 无法停止多线程应用程序中的动态循环【英文标题】:Libev c++ can't stop dynamic loops in multithread application 【发布时间】:2015-06-04 09:10:42 【问题描述】:

我用 c++ 和 libev 编写多线程服务器,但有一个问题。我在主线程中启动 default_loop,并在每个从属线程中创建并启动 dynamic_loop。当我处理信号以停止进程时,我调用 break_loop(ev::ALL)。在该默认事件循环停止但所有动态循环工作后,需要帮助停止动态循环。

环境: 操作系统:Opensuse 13.1

编译器:g++ (SUSE Linux) 4.8.1 20130909

libev:4.15

来源:

#include <vector>
#include <memory>
#include <ev++.h>
#include <thread>
#include <iostream>

class Thread 

public:
    typedef std::thread thread_t;
    Thread() std::cout << "thread created" << std::endl;
    ~Thread() std::cout << "Thread destructed" << std::endl;
    virtual void start() this->thread = thread_t(&Thread::run, this);
    virtual void stop()
    
        std::cout << "unloop" << std::endl;
        std::cout << this->thread.get_id() << std::endl;

        if(this->thread.joinable())
            std::cout << " it's joinable" << std::endl;

        this->loop->break_loop(ev::ALL);

        this->thread.join();
        std::cout << "Thread " << this->thread.get_id() << " stopped" << std::endl;
    

    void run()
    
        this->loop = new ev::dynamic_loop(ev::AUTO);

        this->timer.set(*this->loop);
        this->timer.set<Thread, &Thread::on_timer>(this);
        this->timer.start(1, 1);

        std::cout << "Thread " << this->thread.get_id() << " started" << std::endl;

        this->loop->run(0);

        this->timer.stop();

        std::cout << "Thread " << this->thread.get_id() << " finalized" << std::endl;
    

    void on_timer()
    
        std::cout << "Time event" << std::endl;
    
protected:
    thread_t thread;
    ev::dynamic_loop *loop;
    ev::timer timer;
private:
    Thread(const Thread &) = delete;
    void operator=(const Thread &) = delete;
;

class Server 
public:
    void run()
    
        std::cout << "Start server" << std::endl;

        this->sigint.set<&Server::on_terminate_signal>();
        this->sigint.start(SIGINT);

        this->sigterm.set<&Server::on_terminate_signal>();
        this->sigterm.start(SIGTERM);

        this->sigkill.set<Server::on_terminate_signal>();
        this->sigkill.start(SIGKILL);

        std::vector<Thread*> threads;

        for(auto i = 0; i< 5; i++)
        
            auto buf = new Thread();
            buf->start();
            threads.push_back(buf);
        

        this->loop.run(0);

        this->sigint.stop();
        this->sigterm.stop();
        this->sigkill.stop();

        for(auto *iter: threads)
        
            iter->stop();
            delete (&iter);
        

        std::cout << "Gracefull exit" << std::endl;
    
protected:
    ev::default_loop loop;
    ev::sig sigint;
    ev::sig sigkill;
    ev::sig sigterm;

    static void on_terminate_signal(ev::sig& signal, int)
    
        signal.loop.break_loop(ev::ALL);
        signal.stop();
        std::cout << "Signal handled" << std::endl;
        
;

int main(int, char**)

    std::cout << "libev " << ev::version_major() << "." << ev::version_minor() << std::endl;
    Server server;
    server.run();

    return 0;

输出:

  libev 4.15
    Start server
    thread created
    thread created
    thread created
    thread created
    thread created
    Thread 139639372617472 started
    Thread 139639326365440 started
    Thread 139639337928448 started
    Thread 139639361054464 started
    Thread 139639349491456 started
    Time event
    Time event
    Time event
    Time event
    Time event
    Time event
    Time event
    Time eventTime event

    Time event
    Time event
    Time event
    Time event
    Time event
    Time event
    ^CSignal handled
    unloop
    139639372617472
     it's joinable
    Time eventTime event

    Time event
    Time event
    Time event
    Time event
    Time event
    Time event
    Time event

    Time event

编译标志:-O0 -g -std=c++11

链接器标志:-lev

UPD,带有炒锅代码的来源:

    #include <vector>
    #include <memory>
    #include <ev++.h>
    #include <thread>
    #include <iostream>

    class Thread 
    public:
            typedef std::thread thread_t;
            Thread(): loop(ev::AUTO) std::cout << "thread created" << std::endl;
            virtual ~Thread() std::cout << "Thread destructed" << std::endl;
            virtual void start() this->thread = thread_t(&Thread::run, this);
            virtual void stop()
            
                    std::cout << "Try stopping " << this->thread.get_id() << std::endl;

                    this->stopper.send();
                    this->thread.join();
            

            void run()
            
                    this->timer.set(this->loop);
                    this->timer.set<Thread, &Thread::on_timer>(this);
                    this->timer.start(1, 1);

                    this->stopper.set(this->loop);
                    this->stopper.set<Thread, &Thread::on_stop>(this);
                    this->stopper.start();

                    std::cout << "Thread " << this->thread.get_id() << " started" << std::endl;

                    this->loop.run(0);

                    std::cout << "Thread " << this->thread.get_id() << " finalized" << std::endl;
            
    protected:
            thread_t thread;
            ev::dynamic_loop loop;
            ev::timer timer;
            ev::async stopper;

            void on_timer()
            
                    std::cout << "Time event" << std::endl;
            

            void on_stop()
            
                    std::cout << "On stop event " << std::endl;

                    this->stopper.stop();
                    this->timer.stop();

                    this->loop.break_loop(ev::ALL);
            
    private:
            Thread(const Thread &) = delete;
            void operator=(const Thread &) = delete;
    ;

    class Server 
    public:
            void run()
            
                    std::cout << "Start server" << std::endl;

                    this->sigint.set<&Server::on_terminate_signal>();
                    this->sigint.start(SIGINT);

                    this->sigterm.set<&Server::on_terminate_signal>();
                    this->sigterm.start(SIGTERM);

                    this->sigkill.set<Server::on_terminate_signal>();
                    this->sigkill.start(SIGKILL);

                    std::vector<Thread*> threads;

                    for(auto i = 0; i< 5; i++)
                    
                            auto buf = new Thread();
                            buf->start();
                            threads.push_back(buf);
                    

                    this->loop.run(0);

                    this->sigint.stop();
                    this->sigterm.stop();
                    this->sigkill.stop();

                    for (auto &iter: threads)
                    
                            iter->stop();
                            delete iter;
                    

                    std::cout << "Gracefull exit" << std::endl;
            
    protected:
            ev::default_loop loop;
            ev::sig sigint;
            ev::sig sigkill;
            ev::sig sigterm;

            static void on_terminate_signal(ev::sig& signal, int)
            
                    signal.loop.break_loop(ev::ALL);
                    signal.stop();
                    std::cout << "Signal handled" << std::endl;
            
    ;

    int main(int, char**)
    
            std::cout << "libev " << ev::version_major() << "." << ev::version_minor() << std::endl;
            Server server;
            server.run();

            return 0;
    

【问题讨论】:

【参考方案1】:

回答

您需要在停止包含此计时器的循环之前停止计时器:

移动线:

this->timer.stop();

在此之前:

this->loop->break_loop(ev::ALL);

不要玩原始指针

你可以摆脱指针:

ev::dynamic_loop *loop;

this->loop = new ev::dynamic_loop(ev::AUTO);

并使其成为类变量,在构造函数中初始化:

ev::dynamic_loop 循环;

线程():循环(ev::AUTO)

可能这是个错误

删除 (&iter);

当然,如果你不想删除指向iter的指针。

【讨论】:

【参考方案2】:

你可以使用libev事件来捕捉一个SIGINT信号,这样所有线程都可以正常退出。

【讨论】:

以上是关于Libev C++ 无法停止多线程应用程序中的动态循环的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中的线程内启动和停止循环

C++多线程编程,有没有方法让线程内的一些连续的语句一次执行完,在跳到其它的线程?

如何终止或停止 C++ 中的分离线程?

C ++多线程套接字无法接收客户端数据

多线程编程 实战篇

纯 C++ 中的多线程?