Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way for ObjectReader to use a pre-defined executor #633

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

kineshsatiya
Copy link

No description provided.

throw new Exception("Took too long to fetch object: " + objectName);
} catch (InterruptedException e) {

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the loop, you should probably just invoke executor.shutdownNow() if awaitTermination doesn't return or is itself interrupted, e.g. someone called shutdownNow() on ObjectReader's thread. Something like this:

                finally {
                    executor.shutdown();
                    try {
                        if (!executor.awaitTermination(maxWaitTimeInSeconds, TimeUnit.SECONDS)) {
                            throw new Exception("Took too long to fetch object: " + objectName);
                        }
                    } finally{
                        if(!executor.isTerminated()) {
                            executor.shutdownNow();
                        }
                    }
                }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, swallowing the InterruptedException here seems inappropriate. But I'm also wondering if it's appropriate for the ObjectReader to shutdown itself the executor when it has been provided through withExecutorService(). Shuting it down was making sense when the ObjectReader was creating it itself. But it feels to me that some developer would expect this method to be a way to provide a long running, shared and reused ExecutorService and therefore expect the ObjectReader class to not shut it down.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @mfiguiere that generally any logic which creates an executor should be responsible for its life-cycle.

@kineshsatiya, is the new feature to set an external executor absolutely required for the shutdown bug fix?

We need to restrict master to only critical bug fixes. The ability to pass an external executor seems more like a (likely) small performance optimization given that ObjectReader's use case is transferring large objects.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @jeremycnf and @mfiguiere for quick reviews.

The original intent for users to be able to pass an external executor to ObjectReader is performance related ( to avoid having zombie threads). Calling shutdown with external executor service would have defeated that purpose. I've made the changes that does not shutdown the external service.

throw new Exception("Took too long to fetch object: " + objectName);
} finally {
if (!executor.isTerminated())
executor.shutdownNow();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this call merits some diagnostics - logging what it returns and whether or not the tasks have actually terminated. Here is what shutdownNow() documentation says:

"This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate."

I know I was the one who suggested it, but it seems like that even with this change (which I believe should help a lot), there is still potential for getting into thread count explosion. I think it would be good to at least wait for a few seconds here and log whether or not threads have terminated.

(Completely agree with others on inappropriateness of shutting down a shared executor - it could be used in parallel by multiple ObjectReaders with clearly unexpected results.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Logging is a good idea.

The only reliable way to kill executor threads still not terminated after shutdownNow() is to kill the JVM itself; in such case we'd need to further investigate whether this recipe is the root cause. If the block is due to an optionally-specified callback, the caller would need to investigate their callback logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants