diff --git a/ch.psi.fda/pom.xml b/ch.psi.fda/pom.xml index 46f7f4d..ab85943 100644 --- a/ch.psi.fda/pom.xml +++ b/ch.psi.fda/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ch.psi fda - 1.1.30 + 1.1.31 diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java index b015045..e408fc8 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java @@ -35,6 +35,9 @@ public class ShellAction implements Action{ // Get Logger private static Logger logger = Logger.getLogger(ShellAction.class.getName()); + private volatile Process process; + private volatile boolean abort = false; + /** * Name (full path if it is not in the system path) of the script to execute when * the execute() function of this action is invoked. @@ -67,15 +70,22 @@ public class ShellAction implements Action{ @Override public void execute() throws InterruptedException { try{ + abort = false; logger.fine("Execute script "+script); - Process process = Runtime.getRuntime().exec(script); + process = Runtime.getRuntime().exec(script); int exitValue = process.waitFor(); logger.fine("Script ["+script+"] return value: "+exitValue); - // Check script exit value to 0 if != 0 then throw an runtime exception - if(exitValue != 0){ - throw new RuntimeException("Script ["+script+"] returned with an exit value not equal to 0"); + if(abort){ + throw new RuntimeException("Script ["+script+"] was aborted"); } + else{ + // Check script exit value to 0 if != 0 then throw an runtime exception + if(exitValue != 0){ + throw new RuntimeException("Script ["+script+"] returned with an exit value not equal to 0"); + } + } + process = null; // Ensure that the process is null } catch(IOException e){ // Convert Exception into unchecked RuntimeException @@ -88,7 +98,12 @@ public class ShellAction implements Action{ */ @Override public void abort() { + abort=true; // This action cannot be aborted, therefore this function is not implemented. + if(process!=null){ + // Terminate process via kill + process.destroy(); + } } /* (non-Javadoc) diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java index e06d02f..f172a28 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/loops/ActorSensorLoop.java @@ -191,151 +191,157 @@ public class ActorSensorLoop implements ActionLoop { // Variable to store the last guard status boolean guardOK=true; - // Execute loop logic - while(loop){ + try{ - if(guardOK){ + // Execute loop logic + while(loop){ - - // If actors are defined for the loop check whether all of them - // have a next step defined if there is no actor defined only run this loop once - if(actors.size()>0){ - // Check whether the actors of this loop have a next step. If not - // abort the loop - boolean hasNext = true; - for(Actor actor: actors){ - if(!actor.hasNext()){ - hasNext=false; - break; // Stop actor check loop + if(guardOK){ + + + // If actors are defined for the loop check whether all of them + // have a next step defined if there is no actor defined only run this loop once + if(actors.size()>0){ + // Check whether the actors of this loop have a next step. If not + // abort the loop + boolean hasNext = true; + for(Actor actor: actors){ + if(!actor.hasNext()){ + hasNext=false; + break; // Stop actor check loop + } + } + + // If not all actors have a next step abort the loop + if(!hasNext){ + break; // Stop action loop } } - - // If not all actors have a next step abort the loop - if(!hasNext){ - break; // Stop action loop + else{ + // No actors defined, only run loop once + loop = false; } - } - else{ - // No actors defined, only run loop once - loop = false; - } - - - - // Execute pre actor actions - for(Action action: preActorActions){ - action.execute(); - } - - if(abort){ // End loop if abort was issued - break; - } - - // Set actors -// for(Actor actor: actors){ -// actor.set(); -// } - // Parallel set of the actors - try { - for (Future f : executorService.invokeAll(pactors)) { - f.get(); //Blocks until the async set() is finished - } - } catch (ExecutionException e) { - throw new RuntimeException("Setting the actors failed",e); - } - - // Execute post actor actions - for(Action action: postActorActions){ - action.execute(); - } - - if(abort){ // End loop if abort was issued - break; - } - - } - - if(guard!=null){ - // Initialize guard - guard.init(); - guardOK=guard.check(); - - // Wait until guard is ok - while(!guardOK){ - logger.info("Waiting for guard condition(s) to be met"); - // Sleep 100 milliseconds before next check - Thread.sleep(1000); + - // Check whether the loop is not aborted, if it is aborted - // break the wait loop (afterwards also the loop loop is aborted) - if(!loop){ + + // Execute pre actor actions + for(Action action: preActorActions){ + action.execute(); + } + + if(abort){ // End loop if abort was issued break; } + // Set actors + // for(Actor actor: actors){ + // actor.set(); + // } + // Parallel set of the actors + try { + for (Future f : executorService.invokeAll(pactors)) { + f.get(); //Blocks until the async set() is finished + } + } catch (ExecutionException e) { + throw new RuntimeException("Setting the actors failed",e); + } + + // Execute post actor actions + for(Action action: postActorActions){ + action.execute(); + } + + if(abort){ // End loop if abort was issued + break; + } + + } + + if(guard!=null){ + // Initialize guard guard.init(); guardOK=guard.check(); + + // Wait until guard is ok + while(!guardOK){ + logger.info("Waiting for guard condition(s) to be met"); + // Sleep 100 milliseconds before next check + Thread.sleep(1000); + + // Check whether the loop is not aborted, if it is aborted + // break the wait loop (afterwards also the loop loop is aborted) + if(!loop){ + break; + } + + guard.init(); + guardOK=guard.check(); + } + + // If loop is aborted proceed to next iteration an abort loop + if(!loop){ + continue; + } + } + + // Execute pre sensor actions + for(Action action: preSensorActions){ + action.execute(); + } + + if(abort){ // End loop if abort was issued + break; + } + + // Read sensors + DataMessage message = new DataMessage(); + for(Sensor sensor: sensors){ + // Readout sensor + Object o = sensor.read(); + // Add sensor data item to message + message.getData().add(o); + } + + // Execute post sensor actions + for(Action action: postSensorActions){ + action.execute(); + } + + if(abort){ // End loop if abort was issued + break; + } + + // Check guard if one is registered + if(guard!=null){ + guardOK=guard.check(); } - // If loop is aborted proceed to next iteration an abort loop - if(!loop){ - continue; - } - } - - // Execute pre sensor actions - for(Action action: preSensorActions){ - action.execute(); - } - - if(abort){ // End loop if abort was issued - break; - } - - // Read sensors - DataMessage message = new DataMessage(); - for(Sensor sensor: sensors){ - // Readout sensor - Object o = sensor.read(); - // Add sensor data item to message - message.getData().add(o); - } - - // Execute post sensor actions - for(Action action: postSensorActions){ - action.execute(); - } - - if(abort){ // End loop if abort was issued - break; - } - - // Check guard if one is registered - if(guard!=null){ - guardOK=guard.check(); - } - - if(guardOK){ - - // Post a message with the sensor data - dataQueue.put(message); + if(guardOK){ - // Loop all configured ActionLoop objects - for(ActionLoop actionLoop: actionLoops){ - actionLoop.execute(); + // Post a message with the sensor data + dataQueue.put(message); + + // Loop all configured ActionLoop objects + for(ActionLoop actionLoop: actionLoops){ + actionLoop.execute(); + } } } + + // Execute post actions + for(Action action: postActions){ + action.execute(); + } + } - - // Execute post actions - for(Action action: postActions){ - action.execute(); + finally{ + // Ensure that data stream is terminated ... + + // Issue end of loop control message + // Set iflag of the EndOfStreamMessage according to dataGroup flag of this loop + dataQueue.put(new EndOfStreamMessage(dataGroup)); } - - // Issue end of loop control message - // Set iflag of the EndOfStreamMessage according to dataGroup flag of this loop - dataQueue.put(new EndOfStreamMessage(dataGroup)); - if(zigZag){ // Reverse actors for the next run for(Actor actor: actors){ diff --git a/ch.psi.fda/src/test/resources/home/config/logging.properties b/ch.psi.fda/src/test/resources/home/config/logging.properties index f1781f1..73d2ae3 100644 --- a/ch.psi.fda/src/test/resources/home/config/logging.properties +++ b/ch.psi.fda/src/test/resources/home/config/logging.properties @@ -3,7 +3,7 @@ handlers = java.util.logging.ConsoleHandler # Set the default logging level for the root logger -.level=INFO +.level=ALL # Set the default logging level for new ConsoleHandler instances java.util.logging.ConsoleHandler.level=ALL diff --git a/ch.psi.fda/src/test/resources/home/scans/templates/scan1d-shellactionError.xml b/ch.psi.fda/src/test/resources/home/scans/templates/scan1d-shellactionError.xml new file mode 100644 index 0000000..10d2dd2 --- /dev/null +++ b/ch.psi.fda/src/test/resources/home/scans/templates/scan1d-shellactionError.xml @@ -0,0 +1,25 @@ + + + + + + + + 0.0 + 8.0 + 0.5 + + + + + + + + + + + + + diff --git a/ch.psi.fda/src/test/resources/testscripts/errorscript.sh b/ch.psi.fda/src/test/resources/testscripts/errorscript.sh new file mode 100755 index 0000000..874861e --- /dev/null +++ b/ch.psi.fda/src/test/resources/testscripts/errorscript.sh @@ -0,0 +1,11 @@ +#!/bin/bash +echo "Error Script" +if [ -f /tmp/error.tmp ]; then + echo "Error Occured" + sleep 20 + exit 1 +fi +sleep 4 +touch /tmp/error.tmp +echo "Return Error Script" +exit 0