Work around buggy MyersDiff by killing threads
The JGIt MyersDiff class contains a bug that triggers an infinite loop
on only certain input files. Most source code is able to be processed
in a reasonable time bound, but some just steal a thread and never
return to the caller.
Implement a custom thread pool that is used to invoke MyersDiff for
the intraline difference data. If the worker thread doesn't end
within the configured time bound (default of 5 seconds), Gerrit
removes the worker from the pool and tries to kill the worker with the
unsafe Thread.stop() method.
A custom thread pool is used to try and make Thread.stop() safe by
having the amount of data accessed by each worker thread be limited to
only the "constant" inputs supplied by the cache lookup request, and
the result that the thread would return.
If any locks are released early as a result of ThreadDeath going up
the worker thread stack at worst only the incoming or outgoing queues
that are private to that worker will be corrupted. Since these queues
are private to the worker, and to the thread that is currently
borrowing this worker from the pool (and who is also now killing it),
we can safely ensure that the queues won't be touched after the
Thread.stop() request is made. This wouldn't be true if we reused any
of the java.util.concurrent thread pool utilities.
This change doesn't actually fix the MyersDiff bug, so we're leaving
issue 487 open. It does however reduce the impact by trying to abort
the runaway thread, and still show the file with intraline difference
support disabled on just that one file.
Bug: issue 487
Signed-off-by: Shawn O. Pearce <firstname.lastname@example.org>
12 files changed