Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jeromq: closing context fails

EDIT: solved myself, see below (although I'm not sure if I've stumbled upon a bug here)

Using the simple hello-world request-reply example below, closing the context at the end of the program fails: Either it simply hangs at ctx.close() or it throws the following exception:

Exception in thread "reaper-1" java.lang.NullPointerException
    at zmq.Ctx.destroy_socket(Ctx.java:327)
    at zmq.ZObject.destroy_socket(ZObject.java:144)
    at zmq.SocketBase.check_destroy(SocketBase.java:938)
    at zmq.SocketBase.start_reaping(SocketBase.java:753)
    at zmq.Reaper.process_reap(Reaper.java:133)
    at zmq.ZObject.process_command(ZObject.java:114)
    at zmq.Reaper.in_event(Reaper.java:90)
    at zmq.Poller.run(Poller.java:233)
    at java.lang.Thread.run(Thread.java:724)

Either way, the program does not halt.

Here is the code (please note that the sockets are both closed within the threads that create them):

import org.zeromq.ZMQ;
import org.zeromq.ZContext;

public class App {
    public static void main(String[] args) throws InterruptedException {
        final ZContext ctx = new ZContext();

        final Thread t1 = new Thread() {
            @Override
            public void run() {
                ZMQ.Socket socket = ctx.createSocket(ZMQ.REQ);
                socket.connect("inproc://test");
                System.err.format("[Thread %s] socket connected%n", Thread.currentThread().getId());
                socket.send("hello");
                System.err.format("[Thread %s] hello sent%n", Thread.currentThread().getId());
                String result = socket.recvStr();
                System.err.format("[Thread %s] received response '%s'%n", Thread.currentThread()
                        .getId(), result);
                socket.close();
                System.err.format("[Thread %s] socket closed%n", Thread.currentThread().getId());
                ctx.destroySocket(socket);
                System.err.format("[Thread %s] socket destroyed%n", Thread.currentThread().getId());
            }
        };
//      t1.start();

        final Thread t2 = new Thread() {
            @Override
            public void run() {
                ZMQ.Socket socket = ctx.createSocket(ZMQ.REP);
                socket.setLinger(10000);
                socket.bind("inproc://test");
                System.err.format("                    [Thread %s] socket bound%n", Thread.currentThread().getId());
                String request = socket.recvStr();
                assert request == "hello";
                System.err.format("                    [Thread %s] received request '%s'%n", Thread.currentThread()
                        .getId(), request);
                socket.send("world");
                socket.close();
                System.err.format("                    [Thread %s] socket closed%n", Thread.currentThread().getId());
                ctx.destroySocket(socket);
                System.err.format("                    [Thread %s] socket destroyed%n", Thread.currentThread().getId());
            }
        };
        t2.start();
        Thread.sleep(2000);
        t1.start();

        System.err.println("waiting on the threads to finish...");
        t1.join();
        t2.join();

        System.err.println("closing context...");
        ctx.close();
    }
}

EDIT: solved

It turns out that socket.close() does not work, and that ctx.destroySocket(socket) alone suffices (it also closes the socket). So removing socket.close() resolves the issue. Is this a bug?

like image 582
Kevin Bader Avatar asked Jul 24 '13 10:07

Kevin Bader


2 Answers

Had the same issue; it's not a bug, use one or the other, not both, but use the ZContext methods, they're more efficient.

close() explicitly closes the socket, so calling ctx.destroySocket() afterwards throws that exception. If you need to close the socket, use ctx.destroySocket(), don't use close() at all, and always use ctx.destroy() to close the context before shutting down and exiting gracefully, it will automatically close any sockets created from that context.

like image 161
raffian Avatar answered Oct 19 '22 00:10

raffian


I also had a similar problem, and after some surfing I found a discussion about related topics on JeroMQ (java implementation of ZMQ)'s Github site.

https://github.com/zeromq/jeromq/issues/40

It would seem that ZMQ.Context is part of a low level API, while ZContext is a higher level API. Consequently, context.close should not be used with ZContext, while ctx.destroySocket() should. And I'm sure there are a host of other similar issues one should know about.

like image 31
Yngvefaen Avatar answered Oct 19 '22 01:10

Yngvefaen