question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Remove Thread.interrupt() restriction.

See original GitHub issue

The wiki says:

“Context.term() must be called before interrupting a thread by Thread.interrupt. Otherwise internal pipe which is used to signal ZMQ commands will be shutdown unexpectedly.”

However, in some cases this means that there is no clean way for an application to shut down when it is blocked on recv().

Consider a thread (thread B) that is blocked on a socket’s recv().

Suppose the main thread (thread A) of the application wants to shut down, it needs to cleanly terminate thread B. This typically involves sending an interrupt to thread B to unblock, but wait! we need to call Context.term() first. However, the wiki says:

“Close all the sockets properly otherwise Context.term() will wait forever”

OK, we need to close the socket first, but wait! The ZMQ guide says:

“Isolate data privately within its thread and never share data in multiple threads. The only exception to this are ØMQ contexts, which are threadsafe.”

Hmm, so the only safe way to close the socket is on the thread that is currently blocked (thread B), too bad we can’t do that.

So now the only way for thread B to unblock is to wait for a new message or a timeout (which may have been set to no timeout). If there are no more messages and there is no timeout, the thread will be blocked indefinitely. But regardless, there should be a means to preemptively unblock the thread.

Even if we were to ignore the shutdown problem, this restriction also leads to more awkward code because now the context needs to be exposed to other threads where it might not have been necessary without the restriction.

In fact, if you look at the Java example in the ZMQ guide and even the examples in this repository, it breaks the interrupt rule.

This is a pretty common pattern you see throughout the code:

while (!Thread.currentThread ().isInterrupted ()) {
    ...
}
receiver.close ();
context.term ();

Notice how it expects an interrupt before closing the socket and context.

Issue Analytics

  • State:closed
  • Created 10 years ago
  • Comments:16 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
daveyarwoodcommented, Apr 25, 2017

Today I stumbled upon this, which is very informative about Thread.interrupt(), Thread.interrupted, and InterruptedException in Java.

I looked through the codebase and found 2 places where we appear to be swallowing an InterruptedException – I made a PR to fix that: #423.

I don’t think that my PR solves this issue, but hopefully it is a step in the right direction.

At this point, I’m thinking the problem is that we aren’t checking Thread.interrupted() often enough in our code, and there must be at least one place where we should be detecting that the thread is interrupted and taking the opportunity to shut down cleanly, but we aren’t.

2reactions
miniwaycommented, Nov 25, 2013

Thank you for the comment.

“Close all the sockets properly otherwise Context.term() will wait forever” not actually means socket.close must be called before Context.term is called. Because Context.term() waits until all the ZMQ sockets are closed, a thread which creates the sockets has responsibility to close its sockets.

The pattern in the guide is also misleading. It was my boring translation of C examples.

while (true) { .. }

must have been correct guide. Sorry for the confusing.

Other example might be useful for clean exit is https://github.com/zeromq/jeromq/blob/master/src/test/java/guide/interrupt.java

When the term is called, all the blocking call(usually recv) will raise an Exception, then you can do any cleanup including closing zmq socket.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Killing thread after some specified time limit in Java
When time limit is reached your thread will get interrupted() flag set to true and it's your job to handle this situation correctly...
Read more >
Killing threads in Java - GeeksforGeeks
Using Thread.interrupt() method: Whenever an interrupt has been sent to a thread, it should stop whatever task it is performing. It is very ......
Read more >
Interrupting a blocked thread | Concurrency in Java - InformIT
When the Timer runs out, the object's interrupt( ) method is called. Then the blocked reference is set to null so the garbage...
Read more >
Thread interruption in Java (ctd) - Javamex
interrupt() will not automatically interrupt the thread if it does not make any blocking calls;; but we can manually check for the interrupted...
Read more >
Interrupts - Essential Java Classes
Invoking Thread.interrupt sets this flag. When a thread checks for an interrupt by invoking the static method Thread.interrupted , interrupt status is cleared....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found