From fcae1c9785ae3136dc89f97bccf4e8b81184c51b Mon Sep 17 00:00:00 2001 From: Dan Ambrosio <dan.ambrosio@stratom.com> Date: Fri, 3 Mar 2017 11:46:49 -0800 Subject: [PATCH] This closes rosjava/rosjava_core#233. Adds fix for shutting down DefaultNodeMainExecutor ListenerGroup to prevent leak in android when activities are destroyed. Added ability to remove listener from ListenerGroup to fix android_core issue #254. --- .../org/ros/concurrent/EventDispatcher.java | 5 +++++ .../org/ros/concurrent/ListenerGroup.java | 20 +++++++++++++++++++ .../org/ros/internal/node/DefaultNode.java | 5 +++++ .../org/ros/node/DefaultNodeMainExecutor.java | 1 + rosjava/src/main/java/org/ros/node/Node.java | 6 ++++++ 5 files changed, 37 insertions(+) diff --git a/rosjava/src/main/java/org/ros/concurrent/EventDispatcher.java b/rosjava/src/main/java/org/ros/concurrent/EventDispatcher.java index 428d9256..83985f6f 100644 --- a/rosjava/src/main/java/org/ros/concurrent/EventDispatcher.java +++ b/rosjava/src/main/java/org/ros/concurrent/EventDispatcher.java @@ -42,4 +42,9 @@ public class EventDispatcher<T> extends CancellableLoop { SignalRunnable<T> signalRunnable = events.takeFirst(); signalRunnable.run(listener); } + + public T getListener() + { + return listener; + } } \ No newline at end of file diff --git a/rosjava/src/main/java/org/ros/concurrent/ListenerGroup.java b/rosjava/src/main/java/org/ros/concurrent/ListenerGroup.java index ae7deb38..29a8ccb2 100644 --- a/rosjava/src/main/java/org/ros/concurrent/ListenerGroup.java +++ b/rosjava/src/main/java/org/ros/concurrent/ListenerGroup.java @@ -101,6 +101,25 @@ public class ListenerGroup<T> { return addAll(listeners, DEFAULT_QUEUE_CAPACITY); } + /** + * Removes and cancels the {@EventDispatcher} specified by the listener + * from the {@link ListenerGroup}. + * @param listener the listener to remove + * @return flag indicating successful removal + */ + public boolean remove(T listener) + { + for (EventDispatcher<T> eventDispatcher : eventDispatchers) { + if(listener.equals(eventDispatcher.getListener())) + { + eventDispatcher.cancel(); + eventDispatchers.remove(eventDispatcher); + return true; + } + } + return false; + } + /** * @return the number of listeners in the group */ @@ -151,5 +170,6 @@ public class ListenerGroup<T> { for (EventDispatcher<T> eventDispatcher : eventDispatchers) { eventDispatcher.cancel(); } + eventDispatchers.clear(); } } diff --git a/rosjava/src/main/java/org/ros/internal/node/DefaultNode.java b/rosjava/src/main/java/org/ros/internal/node/DefaultNode.java index ec363955..81386ceb 100644 --- a/rosjava/src/main/java/org/ros/internal/node/DefaultNode.java +++ b/rosjava/src/main/java/org/ros/internal/node/DefaultNode.java @@ -493,6 +493,11 @@ public class DefaultNode implements ConnectedNode { }); } + @Override + public void removeListeners() { + nodeListeners.shutdown(); + } + /** * SignalRunnable all {@link NodeListener}s that the {@link Node} has started. * <p> diff --git a/rosjava/src/main/java/org/ros/node/DefaultNodeMainExecutor.java b/rosjava/src/main/java/org/ros/node/DefaultNodeMainExecutor.java index 96d75754..7ae60746 100644 --- a/rosjava/src/main/java/org/ros/node/DefaultNodeMainExecutor.java +++ b/rosjava/src/main/java/org/ros/node/DefaultNodeMainExecutor.java @@ -213,6 +213,7 @@ public class DefaultNodeMainExecutor implements NodeMainExecutor { * the {@link Node} to unregister */ private void unregisterNode(Node node) { + node.removeListeners(); connectedNodes.get(node.getName()).remove(node); nodeMains.remove(node); } diff --git a/rosjava/src/main/java/org/ros/node/Node.java b/rosjava/src/main/java/org/ros/node/Node.java index ea88d768..9e47943c 100644 --- a/rosjava/src/main/java/org/ros/node/Node.java +++ b/rosjava/src/main/java/org/ros/node/Node.java @@ -126,4 +126,10 @@ public interface Node { * Shut the node down. */ void shutdown(); + + /** + * Stops and Clears node listeners. + */ + + void removeListeners(); } -- GitLab