NIFI-4436: Fixed bug that causes a deadlock when changing version of a PG. Before this patch, an update would obtain a write lock and then recurse downward through the child groups, obtaining write locks to update variable registries. At the same time, if a Processor is obtaining a Controller Service, it will obtain a Read Lock on the Process Group and then recurse upward through the ancestors, obtaining Read Lock. If the timing is right, we can have a group obtain a read lock, then try to obtain its parent's Read Lock. At the same time, an update to the group could hold the Write Lock on the Process Group and attempt to obtain a Write Lock on child (where the Processor lives), resulting in a deadlock.
Signed-off-by: Matt Gilman <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/0127b026 Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/0127b026 Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/0127b026 Branch: refs/heads/master Commit: 0127b02617530491a1a55aa72395cee583083956 Parents: c5b0931 Author: Mark Payne <[email protected]> Authored: Sat Dec 30 14:16:26 2017 -0500 Committer: Bryan Bende <[email protected]> Committed: Mon Jan 8 12:44:56 2018 -0500 ---------------------------------------------------------------------- .../apache/nifi/groups/StandardProcessGroup.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/0127b026/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java index 5d5d0f4..bc5ef29 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java @@ -2028,19 +2028,23 @@ public final class StandardProcessGroup implements ProcessGroup { @Override public Set<ControllerServiceNode> getControllerServices(final boolean recursive) { + final Set<ControllerServiceNode> services = new HashSet<>(); + readLock.lock(); try { - final Set<ControllerServiceNode> services = new HashSet<>(); services.addAll(controllerServices.values()); - - if (recursive && parent.get() != null) { - services.addAll(parent.get().getControllerServices(true)); - } - - return services; } finally { readLock.unlock(); } + + if (recursive) { + final ProcessGroup parentGroup = parent.get(); + if (parentGroup != null) { + services.addAll(parentGroup.getControllerServices(true)); + } + } + + return services; } @Override
