Skip to content

Commit 09c0e68

Browse files
authored
Avoid blocking forever in RCLFuture.get() with timeout (#78)
Add overloads for spinOnce methods to include a timeout argument and call this when spinning in the future. This fixes a bug where the future.get(...) call blocks forever, e.g. when waiting on a service response and the service becomes unavailable. Signed-off-by: Jacob Perron <jacob@openrobotics.org>
1 parent 2f7f46a commit 09c0e68

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

rcljava/src/main/java/org/ros2/rcljava/RCLJava.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,22 +287,61 @@ public static void spin(final ComposableNode composableNode) {
287287
getGlobalExecutor().removeNode(composableNode);
288288
}
289289

290-
public static void spinOnce(final Node node) {
290+
/**
291+
* Execute one callback for a @{link Node}.
292+
*
293+
* Wait until a callback becomes ready and then execute it.
294+
*
295+
* @param node The node to spin on.
296+
* @param timeout The time to wait for a callback to become ready in nanoseconds.
297+
* If a timeout occurs, then nothing happens and this method returns.
298+
*/
299+
public static void spinOnce(final Node node, long timeout) {
291300
ComposableNode composableNode = new ComposableNode() {
292301
public Node getNode() {
293302
return node;
294303
}
295304
};
296305
getGlobalExecutor().addNode(composableNode);
297-
getGlobalExecutor().spinOnce();
306+
getGlobalExecutor().spinOnce(timeout);
298307
getGlobalExecutor().removeNode(composableNode);
299308
}
300309

301-
public static void spinOnce(final ComposableNode composableNode) {
310+
/**
311+
* Execute one callback for a @{link Node}.
312+
*
313+
* Wait until a callback becomes ready and then execute it.
314+
*
315+
* @param node The node to spin on.
316+
*/
317+
public static void spinOnce(final Node node) {
318+
RCLJava.spinOnce(node, -1);
319+
}
320+
321+
/**
322+
* Execute one callback for a @{link ComposableNode}.
323+
*
324+
* Wait until a callback becomes ready and then execute it.
325+
*
326+
* @param composableNode The composable node to spin on.
327+
* @param timeout The time to wait for a callback to become ready in nanoseconds.
328+
* If a timeout occurs, then nothing happens and this method returns.
329+
*/
330+
public static void spinOnce(final ComposableNode composableNode, long timeout) {
302331
getGlobalExecutor().addNode(composableNode);
303-
getGlobalExecutor().spinOnce();
332+
getGlobalExecutor().spinOnce(timeout);
304333
getGlobalExecutor().removeNode(composableNode);
305334
}
335+
/**
336+
* Execute one callback for a @{link ComposableNode}.
337+
*
338+
* Wait until a callback becomes ready and then execute it.
339+
*
340+
* @param composableNode The composable node to spin on.
341+
*/
342+
public static void spinOnce(final ComposableNode composableNode) {
343+
RCLJava.spinOnce(composableNode, -1);
344+
}
306345

307346
public static void spinSome(final Node node) {
308347
ComposableNode composableNode = new ComposableNode() {

rcljava/src/main/java/org/ros2/rcljava/concurrent/RCLFuture.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ public final V get(final long timeout, final TimeUnit unit)
7373

7474
while (RCLJava.ok()) {
7575
if (executor != null) {
76-
executor.spinOnce();
76+
executor.spinOnce(timeoutNS);
7777
} else {
7878
Node node = nodeReference.get();
7979
if (node == null) {
8080
return null; // TODO(esteve) do something
8181
}
82-
RCLJava.spinOnce(node);
82+
RCLJava.spinOnce(node, timeoutNS);
8383
}
8484

8585
if (isDone()) {

0 commit comments

Comments
 (0)