Ignore:
Timestamp:
2017-05-01T20:07:17+12:00 (7 years ago)
Author:
ak19
Message:
  1. Correcting switch statement in SafeProcess and tidying up some debugging. 2. GShell needs to have its own LineByLineHandlers not CustomProcessHandlers, since most of the err/out stream processing code should be the default provided by SafeProcess. 3. GShell.gotException wasn't being called during an expected InterruptedException on Cancel, so corrected that to make the code write a message to the DebugStream as the original code did when a build operation had been cancelled.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/shell/GShell.java

    r31638 r31639  
    152152       } */
    153153
     154    // This method is only used by old_runLocal(). If that is removed, then remove this too
    154155    protected StringBuffer get_stream_char(InputStreamReader isr, StringBuffer line_buffer,
    155156                   BufferedOutputStream bos) throws IOException
     
    224225    // old_runLocal uses a potentially unsafe way of running a process and an inefficient way of reading
    225226    // from the process stdout and stderr streams. Replaced by new runLocal() which uses SafeProcess and
    226     // the new CustomProcessHandler inner class instantiated for each of the 2 process output streams.
     227    // the new LineByLineHandler inner class instantiated for each of the 2 process output streams.
     228    // If this method is ever removed from the file, can remove its helper get_stream_char() too.
    227229    private void old_runLocal(String[] args, BufferedOutputStream bos)
    228230    {
     
    354356   
    355357    prcs = new SafeProcess(args);
    356     SafeProcess.CustomProcessHandler processOutHandler
    357         = new SynchronizedProcessHandler(bos, SafeProcess.STDOUT);
    358     SafeProcess.CustomProcessHandler processErrHandler
    359         = new SynchronizedProcessHandler(bos, SafeProcess.STDERR);
     358    SafeProcess.LineByLineHandler processOutLineHandler
     359        = new SynchronizedLineByLineHandler(bos, SafeProcess.STDOUT);
     360    SafeProcess.LineByLineHandler processErrLineHandler
     361        = new SynchronizedLineByLineHandler(bos, SafeProcess.STDERR);
    360362   
    361363    prcs.setExceptionHandler(this);
    362     int exitValue = prcs.runProcess(null, processOutHandler, processErrHandler); // use default procIn handling
     364    int exitValue = prcs.runProcess(processOutLineHandler, processErrLineHandler); // use default procIn handling
    363365   
    364366    if(exitValue == 0) {
    365         System.err.println("*** Exited normally");
     367        //System.err.println("*** Exitted normally");
    366368        status = OK;
    367369        fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null);
    368370    }
    369371    else {
    370         System.err.println("*** Exited abnormally with exit value " + exitValue);
     372        //System.err.println("*** Exitted abnormally with exit value " + exitValue);
    371373        status = ERROR;
    372374        fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null);
     
    385387
    386388        this.interrupt(); // interrupt this thread which is running the SafeProcess prcs
    387         // this will propagate the CANCEL status
     389        // this will propagate the CANCEL status to any worker threads launched by the SafeProcess
    388390        prcs = null;       
    389391    }
    390     hasSignalledStop(); // synchronized. Will set status to CANCELLED in thread-safe manner.   
     392    setStatus(CANCELLED); //or: hasSignalledStop(); // synchronized. Either will set status to CANCELLED in thread-safe manner.
    391393    }
    392394   
     
    691693
    692694    if(e instanceof InterruptedException) {
    693         SafeProcess.log("*** InterruptedException in GShell.runLocal()");
     695        DebugStream.println("We've been asked to stop.");
     696        SafeProcess.log("@@@ Interruption to SafeProcess run by GShell.runLocal()");
    694697        setStatus(CANCELLED); // expected exception
    695698    } else {
     
    706709    // Each instance of this class is run in its own thread by class SafeProcess.InputGobbler.
    707710    // This class deals with each incoming line from the perl process' stderr or stdout streams. One
    708     // instance of this class for each stream. However, since multiple instances of this CustomProcessHandler
    709     // could be (and in fact, are) writing to the same file in their own threads, several objects, not just
    710     // the bufferedwriter object, needed to be made threadsafe.
    711     // This class also handles exceptions during the running of the perl process.
    712     // The runPerlCommand code originally would do a sendProcessStatus on each exception, so we ensure
     711    // instance of this class for each stream. However, since multiple instances of this LineByLineHandler
     712    // are firing off events to the same outputstream object (bos) in their own threads, several objects,
     713    // not just bost, needed to be made threadsafe. So gotLine needs to be synchronized, and created a
     714    // synchronized setStatus() method above too.
     715    // This class also handles exceptions that may occur when reading from the perl process' stderr or stout.
     716    // The old GShell.runLocal() code would set the GShell.status to ERROR on each exception, so we ensure
    713717    // we do that here too, to continue original behaviour. These calls are also synchronized to make their
    714718    // use of the EventListeners threadsafe.
    715     protected class SynchronizedProcessHandler extends SafeProcess.CustomProcessHandler
     719    protected class SynchronizedLineByLineHandler extends SafeProcess.LineByLineHandler
    716720    {
    717721    private final BufferedOutputStream bos; // needs to be final to be able to synchronize on the shared object
    718722   
    719     public SynchronizedProcessHandler(BufferedOutputStream bos, int src) {
     723    public SynchronizedLineByLineHandler(BufferedOutputStream bos, int src) {
    720724        super(src); // will set this.source to STDERR or STDOUT
    721725        this.bos = bos; // caller will close bw, since many more than one
    722                             // SynchronizedProcessHandlers are using it
     726                            // SynchronizedLineByLineHandlers are using it
    723727    }
    724728
    725729    // trying to keep synchronized methods as short as possible
    726     private void logException(Exception e) {
    727         String stream = (this.source == SafeProcess.STDERR) ? "stderr" : "stdout";
    728         String msg = "Got exception when processing the perl process' " + stream + " stream.";
     730    public void gotException(Exception e) {
     731        String msg = "Got exception when processing the perl process' " + SafeProcess.streamToString(this.source) + " stream.";
    729732
    730733        DebugStream.println(msg); // method is already synchronized
     
    732735        SafeProcess.log("*** " + msg, e);
    733736
    734         GShell.this.setStatus(GShell.ERROR);
     737        GShell.this.setStatus(GShell.ERROR); // synchronized
    735738    }
    736739
     
    740743    }
    741744
    742     public void run(Closeable inputStream) {
    743         InputStream is = (InputStream) inputStream;
    744 
    745         BufferedReader br = null;
    746         try {       
    747 
    748         br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    749         String line=null;
    750 
    751         ///while ( !GShell.this.prcs.processRunning() || hasSignalledStop()) { // need to sync on prcs
    752         while ( !Thread.currentThread().isInterrupted() && (line = br.readLine()) != null ) {
    753             this.gotLine(line); // synchronized         
    754         }       
    755 
    756         } catch (Exception e) {
    757         logException(e);
    758         } finally {
    759         System.err.println("*********");
    760         if(Thread.currentThread().isInterrupted()) {
    761             log("We've been asked to stop.");
    762            
    763         }
    764         SafeProcess.closeResource(br);
    765         String stream = (this.source == SafeProcess.STDERR) ? "stderr" : "stdout";
    766         System.err.println("*** In finally of " + stream + " stream");
    767         System.err.println("*********");
    768         }
    769     }
    770 
    771     protected synchronized void gotLine(String line) {
     745    // every time we read a line from the SafeProcess' stderr or stdout stream we come here.
     746    // a different isntance of SynchronizedL
     747    public synchronized void gotLine(String line) {
    772748        fireMessage(GShell.this.type,   // not final, needs synchro
    773749            GShell.this.typeAsString(type) + "> " + line,
Note: See TracChangeset for help on using the changeset viewer.