Added proper abort scenario for shell scripts (kill of process)

Added code to ensure that data stream is terminated (and therefor
written) regardless whether something was failing during a scan.
This commit is contained in:
2012-01-23 12:52:46 +01:00
parent db260dd07c
commit 112396ef71
6 changed files with 189 additions and 132 deletions

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ch.psi</groupId>
<artifactId>fda</artifactId>
<version>1.1.30</version>
<version>1.1.31</version>
<dependencies>
<dependency>

View File

@@ -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)

View File

@@ -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<Object> 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<Object> 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){

View File

@@ -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

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration numberOfExecution="0" xmlns="http://www.psi.ch/~ebner/models/scan/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.psi.ch/~ebner/models/scan/1.0 ../../src/model-v1.xsd">
<!--
1D Scan reading out scalar channels and the timestamp for each point
-->
<data format="txt"/>
<scan id="">
<dimension zigzag="true">
<positioner id="id0" name="MTEST-HW3:MOT1" settlingTime="0.1" xsi:type="LinearPositioner">
<start>0.0</start>
<end>8.0</end>
<stepSize>0.5</stepSize>
</positioner>
<detector id="idD0" xsi:type="ScalarDetector" name="MTEST-HW3:MOT1.RRBV">
<preAction xsi:type="ShellAction" command="/Users/ebner/git/jfda/ch.psi.fda/src/test/resources/testscripts/errorscript.sh"/>
</detector>
<detector id="idD1" xsi:type="ScalarDetector" name="MTEST-HW3:MOT1.RBV"/>
<detector xsi:type="Timestamp" id="timestamp"/>
</dimension>
</scan>
<visualization title="Line Plot One" xsi:type="LinePlot" x="id0" y="idD0"/>
<visualization title="Line Plot Two" xsi:type="LinePlot" x="id0" y="idD1"/>
<visualization xsi:type="LinePlot" x="id0" y="timestamp" title="Timestamp" />
</configuration>

View File

@@ -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