diff --git a/rosjava/src/main/java/org/ros/node/NativeNodeMain.java b/rosjava/src/main/java/org/ros/node/NativeNodeMain.java index c7d2ff4d8c4942ad5d4842bc503657fe0b9b4913..3ed164e205ba26d1bd7a3926fb4e6fe154947d1a 100644 --- a/rosjava/src/main/java/org/ros/node/NativeNodeMain.java +++ b/rosjava/src/main/java/org/ros/node/NativeNodeMain.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2017 Ekumen, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + package org.ros.node; import org.apache.commons.logging.Log; @@ -7,11 +23,13 @@ import org.apache.commons.logging.LogFactory; * A java wrapper to load and run a native-code ROS node. * * Note: there are no actual native methods declared in this class. We only define an interface. The native methods should be declared in the child class. - * + * Native methods' return codes can be handled by the application using {@link #onError(Node, Throwable)}. + * * @author ecorbellini@creativa77.com.ar (Ernesto Corbellini) */ public abstract class NativeNodeMain extends AbstractNodeMain { - + + public static final int SUCCESS = 0; private Log log = LogFactory.getLog(NativeNodeMain.class); private String libName; private String masterUri = null; @@ -19,7 +37,9 @@ public abstract class NativeNodeMain extends AbstractNodeMain { private String nodeName = null; private String[] remappingArguments; private boolean shuttingDown = false; - + protected int executeReturnCode = SUCCESS; + protected int shutdownReturnCode = SUCCESS; + /** * @param libName * The name of the library to load. @@ -36,20 +56,16 @@ public abstract class NativeNodeMain extends AbstractNodeMain { } log.info("Trying to load native library '" + libName + "'..."); - try - { + try { System.loadLibrary(libName); } - catch (SecurityException e) - { + catch (SecurityException e) { log.info("Error loading library! SecurityException"); } - catch (UnsatisfiedLinkError e) - { + catch (UnsatisfiedLinkError e) { log.info("Error loading library! UnsatisfiedLinkError"); } - catch (NullPointerException e) - { + catch (NullPointerException e) { log.info("Error loading library! NullPointerException"); } } @@ -62,10 +78,10 @@ public abstract class NativeNodeMain extends AbstractNodeMain { this(libName, null); } - // These methods define the execution model interface for this node. Return values are error codes (not used by default). + // These methods define the execution model interface for this node. protected abstract int execute(String rosMasterUri, String rosHostName, String rosNodeName, String[] remappingArguments); protected abstract int shutdown(); - + @Override public void onStart(final ConnectedNode connectedNode) { // retain important ROS info @@ -77,19 +93,27 @@ public abstract class NativeNodeMain extends AbstractNodeMain { new Thread() { @Override public void run() { - execute(masterUri, hostName, nodeName, remappingArguments); - + executeReturnCode = execute(masterUri, hostName, nodeName, remappingArguments); + + if (executeReturnCode != SUCCESS) { + onError(connectedNode, new Throwable(nodeName + " execution error code " + executeReturnCode)); + } + // node execution has finished so we propagate the shutdown sequence only if we aren't already shutting down for other reasons - if(!shuttingDown) { + if (!shuttingDown) { connectedNode.shutdown(); } } }.start(); } - + @Override public void onShutdown(Node node) { shuttingDown = true; - shutdown(); + shutdownReturnCode = shutdown(); + + if (shutdownReturnCode != SUCCESS) { + onError(node, new Throwable(nodeName + " shutdown error code " + shutdownReturnCode)); + } } }