Never throw when describing a queued ITS task WorkQueue builds the worker thread's name from a queued task's toString() before it invokes the task. This is done in Gerrit core's WorkQueue and ideally should be fixed to protect its executor against this. An exception from toString() causes the task to be dropped without running and without reporting a rejection or a cancellation, so the in-flight permit which Throttle holds for it is never released, and the plugin loses that capacity for the lifetime of the server. Catch while delegating to the wrapped task's toString() and fall back to its class name, so the thread still gets a name and the task still runs. Change-Id: Ifdb19197deb4dbf1e268cc33b557ec64317fc7e4
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuntimeQueueMap.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuntimeQueueMap.java index df71201..52f06e6 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuntimeQueueMap.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/RuntimeQueueMap.java
@@ -119,7 +119,17 @@ @Override public String toString() { - return activeTask.task.toString(); + try { + Runnable current = activeTask.task; + try { + return current.toString(); + } catch (Exception e) { + logger.atWarning().withCause(e).log("Cannot describe task"); + return current.getClass().getName(); + } + } catch (Exception e) { + return "unknown task"; + } } } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/Throttle.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/Throttle.java index 35734d5..0286570 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/Throttle.java +++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/workflow/Throttle.java
@@ -69,7 +69,16 @@ @Override public String toString() { - return task.toString(); + try { + try { + return task.toString(); + } catch (Exception e) { + logger.atWarning().withCause(e).log("Cannot describe task"); + return task.getClass().getName(); + } + } catch (Exception e) { + return "unknown task"; + } } } }