zeromq / cppzmq

Header-only C++ binding for libzmq
http://www.zeromq.org
MIT License
1.95k stars 757 forks source link

context.shutdown(); cause 'zmq::error_t' what(): Context was terminated in cppzmq #610

Closed fengmao31 closed 1 year ago

fengmao31 commented 1 year ago

The zmq_ctx_shutdown() function shall shutdown the ØMQ context context.

Context shutdown will cause any blocking operations currently in progress on sockets open within context to return immediately with an error code of ETERM.

it means this way will produce errors. but the zmq_errno() return 156384765 no EAGAIN.

image

int main()
{
    zmq::context_t context(1);
    zmq::socket_t subscriber(context, ZMQ_SUB);
    subscriber.connect("tcp://127.0.0.1:6666");
    //subscriber.setsockopt(ZMQ_SUBSCRIBE,"A", 1);
    subscriber.set(zmq::sockopt::subscribe,"A");
    //subscriber.setsockopt(ZMQ_IMMEDIATE,&config_imm, sizeof(char));
    // while(true)
    // {
    context.shutdown();
        //          int rc = zmq_ctx_shutdown(&context);
        //  std::cout<<rc<<std::endl;
        zmq::message_t env;
        subscriber.recv(&env);
        std::string env_str = std::string(static_cast<char*>(env.data()), env.size());
        //std::cout << "Received envelope '" << env_str << env.size()<<"'" << std::endl;

        zmq::message_t zmqmsg;
        zmq::recv_flags flags = zmq::recv_flags::none;
        subscriber.recv(&zmqmsg);

        int size = zmqmsg.size();
        char array[size];
        memcpy(&array, zmqmsg.data(), size);
        // std::cout <<"size"<< size<<std::endl;
        std::shared_ptr<Chatter> msg_ptr_ = std::make_shared<Chatter>();

        msg_ptr_->ParseFromArray(&array, zmqmsg.size());
        std::cout << "Received seq " << msg_ptr_->seq() << " on topic A" << std::endl;
    // }

    subscriber.close();
    context.close();
    return 0;
}

image

zmq_ctx_shutdown: 
terminate called after throwing an instance of 'zmq::error_t'
  what():  Context was terminated
fengmao31 commented 1 year ago

In fact, in my real application, I want to use shutdown to stop the rec in the subthread. but one problem is throw error_t below, another problem is the zmq_errno() is independent in different thread.

gummif commented 1 year ago

I dont understand what the problem is exactly. What you call shutdown all current and further operations will throw error with ETERM code (which you can catch and check for).

fengmao31 commented 1 year ago

I want to use context.shutdown to close the recv() in another thread or that recv thread will block ctrl +c in the terminal. When I use ctrl + c to exit the program, the terminal will show the error.

zmq_ctx_shutdown: 
terminate called after throwing an instance of 'zmq::error_t'
  what():  Context was terminated

I find it is because the throw errot_t in cppzmq. though the doc about zmq say the context.shutdown will free the blocked recv() and return with error EAGAIN. but in the recv fuction the zmq_errno() return 156384765 not EAGAIN. Maybe it is becuse the recv is free and produce new error. The new return cover the EAGAIN. So the if(zmq_errno() == EAGAIN) will not work. The throw errot_t will show the error in the terminal and the ctrl+c cannot exit the program normally.

image

gummif commented 1 year ago

According to this http://api.zeromq.org/master:zmq-ctx-shutdown all operations will return ETERM.

fengmao31 commented 1 year ago

根据这个http://api.zeromq.org/master:zmq-ctx-shutdown,所有操作都将返回ETERM。

but in fact, the error from recv function will cover the ETERM. I shut down the context in the main thread. The recv function in the subthread will throw the error 156384765.

gummif commented 1 year ago

That is ETERM.

fengmao31 commented 1 year ago

那就是ETERM。

Yes. You are right. But throw error_t() in the recv function will make the process cannot exit normally. Do you have good idea? I use try catch to solve it. But it is not a beautiful handling.

gummif commented 1 year ago

I see nothing wrong with try catch, that is how I do it.

fengmao31 commented 1 year ago

Why it is hard to find the try catch handling in the opening source respository in github or business respository