StreamPollFeeder.exception (line 38) is not declared volatile, but is written by the run() thread (line 79) and read from other threads via getException() (line 101). While waitUntilDone() calls join() which establishes a happens-before for reads that happen after the thread terminates, if getException() is called concurrently from another thread before waitUntilDone(), the read may see stale null.
StreamPumper already uses volatile for its exception field (line 41). StreamPollFeeder should follow the same pattern for consistency and correctness.
Fix: declare exception as volatile.
StreamPollFeeder.exception(line 38) is not declaredvolatile, but is written by therun()thread (line 79) and read from other threads viagetException()(line 101). WhilewaitUntilDone()callsjoin()which establishes a happens-before for reads that happen after the thread terminates, ifgetException()is called concurrently from another thread beforewaitUntilDone(), the read may see stalenull.StreamPumperalready usesvolatilefor itsexceptionfield (line 41).StreamPollFeedershould follow the same pattern for consistency and correctness.Fix: declare
exceptionasvolatile.