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

标签 c++ linux multithreading signals libev

我用 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;
    }

最佳答案

回答

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

移动线:

this->timer.stop();

在此之前:

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

不要使用原始指针

您可以摆脱指针:

ev::dynamic_loop *loop;

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

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

ev::dynamic_loop loop;

Thread() : loop(ev::AUTO)

这可能是一个错误

delete (&iter);

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

关于c++ - Libev C++ 无法停止多线程应用程序中的动态循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30639666/

相关文章:

c++ - 对于不断添加和删除的一组元素,我应该使用哪个容器

c++ - Eclipse C++ 多项目公用文件

linux - rdiff-backup fatal error ,找到相关的增量?

asp.net - 在线程内调用存储过程以更新多个记录

java - 使用java模拟对N个传感器进行计数

c++ - 比较两个图

c++ - 是否有以原子方式加载非原子值的函数?

regex - 使用 AWK [或 sed、grep 等] 删除特定行

linux - 在启动时启动自定义屏幕保护程序的行为与手动启动屏幕保护程序不同

.NET CF 3.5 Forms 与仅同步网络设备对话