2

I have a server in java which receive a json file and send it to a C program by jeromq. Until last week I just tested it with a few json. I haven't sent a lot of json until now I have another component to send them.

Glassfish hanged with an error I have never seen before. Something like:

[2014-08-19T09:24:32.446+0000] [glassfish 4.0] [WARNING] [] [java.util.prefs] [tid: _ThreadID=141 _ThreadName=Timer-1] [timeMillis: 1408440272446] [levelValue: 900] [[
Could not lock User prefs.  Unix error code 24.]]

[2014-08-19T09:24:32.446+0000] [glassfish 4.0] [WARNING] [] [java.util.prefs] [tid: _ThreadID=141 _ThreadName=Timer-1] [timeMillis: 1408440272446] [levelValue: 900] [[
  Couldn't flush user prefs: java.util.prefs.BackingStoreException: Couldn't get file lock.]]

And something related to ZMQ:

[2014-08-15T08:23:30.637+0000] [glassfish 4.0] [SEVERE] [] [] [tid: _ThreadID=2432     _ThreadName=Thread-4] [timeMillis: 140809101063$
  zmq.ZError$IOException: java.io.IOException: Too many open files
    at zmq.Signaler.make_fdpair(Signaler.java:87)
    at zmq.Signaler.<init>(Signaler.java:48)
    at zmq.Mailbox.<init>(Mailbox.java:55)
    at zmq.Ctx.<init>(Ctx.java:127)
    at zmq.ZMQ.zmq_ctx_new(ZMQ.java:225)
    at zmq.ZMQ.zmq_init(ZMQ.java:258)
    at org.jeromq.ZMQ$Context.<init>(ZMQ.java:173)
    at org.jeromq.ZMQ.context(ZMQ.java:155)

    ...

    at java.lang.Thread.run(Thread.java:744)
Caused by: java.io.IOException: Too many open files
    at sun.nio.ch.IOUtil.makePipe(Native Method)
    at sun.nio.ch.PipeImpl.<init>(PipeImpl.java:42)
    at sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
    at java.nio.channels.Pipe.open(Pipe.java:150)
    at zmq.Signaler.make_fdpair(Signaler.java:85)
    ... 11 more]] 

I think it could be related to something worng with zmq. If server just receive a few json it never hangs.

I paste my java code, maybe I am doing something wrong or I am not closing something:

First I create a thread to make the zmq sent:

new Thread(new SubmitJSONOnBackground(json, this.context)).start();

My class to run in background:

public class SubmitJSONOnBackground implements Runnable {
private Collection<JSON> jsons;
private ServletContext context;
public SubmitObservationOnBackground(Collection<JSON> json, ServletContext context) {
    this.jsons = json;
    this.context = context;
}
public void run() {
    SubmitJSONHandler submit = new SubmitJSONHandler(jsons, this.context);
    submit.buildAndSubmitJSON();
}

}

And the method which sends zmq:

private boolean submitJSON(String message) {
    ZMQ.Context context = ZMQ.context(1);
    ZMQ.Socket sender = context.socket(ZMQ.PUSH);
    sender.connect("tcp://127.0.0.1:9999");
    sender.send(device, ZMQ.SNDMORE);
    sender.send("json", ZMQ.SNDMORE);
    sender.send("["+message+"]", 0);
    sender.close();
    context.term(); 
    return true;
}

I think it is ok, but since it is failing something related to ZMQ I am not sure it is ok or not.

Ganesh Gaxy
  • 657
  • 5
  • 11
Biribu
  • 3,615
  • 13
  • 43
  • 79
  • Are you handling any exceptions thrown by the `submitJSON` method? Probably the sender socket is not being closed properly and file handles are being exhausted. Use a try .. finally block and set a linger before closing the socket. – jschiavon Aug 21 '14 at 17:42
  • sorry, what is a linger? So you mean before submitJSON calling, set a try and after that, a finally without catch. I close the socket before return so I should set that "linger" there. Could you give me an example? – Biribu Aug 22 '14 at 07:22
  • Try without a catch is legal. In regards to linger, literally from the reference manual: The linger period determines how long pending messages which have yet to be sent to a peer shall linger in memory after a socket is closed with zmq_close(3), and further affects the termination of the socket's context with zmq_term(3). Check [http://api.zeromq.org/4-0:zmq-setsockopt] – jschiavon Aug 22 '14 at 12:31
  • @jschiavon Meddling with linger will not solve an FD exhaustion problem. OP please ignore this advice. – user207421 Aug 25 '14 at 05:18

1 Answers1

4

It's not idiomatic to create and destroy both the Context and Socket especially in a tight loop. You should only ever create one context and inject it into your application. You'll be far better off if you cache the socket as well.

Trevor Bernard
  • 992
  • 10
  • 13
  • In that case I should create a class with singleton to have a unique instance and just call to send2ZMQ... – Biribu Aug 25 '14 at 16:20
  • I am creating singleton pattern. I set the ZMQ.context, context.socket and sender.connect in constructor but I don't know what to do with close and term calls. I understand I should not call them anytime because I will never close the socket but I am not sure. – Biribu Aug 26 '14 at 07:40
  • 1
    This is why I prefer managing the life cycle of my Objects. I would create the context outside the scope of my application pass it in. I would then create some sort of exit handler that closes it's resources when the application terminates. Once this is out of scope, I would terminate the context. Something along the lines of: https://gist.github.com/trevorbernard/d538ca2df3a847b869f9 – Trevor Bernard Aug 26 '14 at 15:27
  • The problem of my application is that it is a server so usually it should not finish never. Anyway, I have solved the problem I think. I updated the jeromq version and now it doesn't crash. Also I created a singleton but opening context 1 time and never closing it (I guess I should add it somewhere). I will reward your answer because singleton will help me in future. Thanks for your time Trevor. – Biribu Aug 26 '14 at 16:01