- Timestamp:
- 2017-05-01T20:07:17+12:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/gli/src/org/greenstone/gatherer/shell/GShell.java
r31638 r31639 152 152 } */ 153 153 154 // This method is only used by old_runLocal(). If that is removed, then remove this too 154 155 protected StringBuffer get_stream_char(InputStreamReader isr, StringBuffer line_buffer, 155 156 BufferedOutputStream bos) throws IOException … … 224 225 // old_runLocal uses a potentially unsafe way of running a process and an inefficient way of reading 225 226 // 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. 227 229 private void old_runLocal(String[] args, BufferedOutputStream bos) 228 230 { … … 354 356 355 357 prcs = new SafeProcess(args); 356 SafeProcess. CustomProcessHandler processOutHandler357 = new Synchronized ProcessHandler(bos, SafeProcess.STDOUT);358 SafeProcess. CustomProcessHandler processErrHandler359 = new Synchronized ProcessHandler(bos, SafeProcess.STDERR);358 SafeProcess.LineByLineHandler processOutLineHandler 359 = new SynchronizedLineByLineHandler(bos, SafeProcess.STDOUT); 360 SafeProcess.LineByLineHandler processErrLineHandler 361 = new SynchronizedLineByLineHandler(bos, SafeProcess.STDERR); 360 362 361 363 prcs.setExceptionHandler(this); 362 int exitValue = prcs.runProcess( null, processOutHandler, processErrHandler); // use default procIn handling364 int exitValue = prcs.runProcess(processOutLineHandler, processErrLineHandler); // use default procIn handling 363 365 364 366 if(exitValue == 0) { 365 System.err.println("*** Exited normally");367 //System.err.println("*** Exitted normally"); 366 368 status = OK; 367 369 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Success"), status, null); 368 370 } 369 371 else { 370 System.err.println("*** Exited abnormally with exit value " + exitValue);372 //System.err.println("*** Exitted abnormally with exit value " + exitValue); 371 373 status = ERROR; 372 374 fireMessage(type, typeAsString(type) + "> " + Dictionary.get("GShell.Failure"), status, null); … … 385 387 386 388 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 388 390 prcs = null; 389 391 } 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. 391 393 } 392 394 … … 691 693 692 694 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()"); 694 697 setStatus(CANCELLED); // expected exception 695 698 } else { … … 706 709 // Each instance of this class is run in its own thread by class SafeProcess.InputGobbler. 707 710 // 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 713 717 // we do that here too, to continue original behaviour. These calls are also synchronized to make their 714 718 // use of the EventListeners threadsafe. 715 protected class Synchronized ProcessHandler extends SafeProcess.CustomProcessHandler719 protected class SynchronizedLineByLineHandler extends SafeProcess.LineByLineHandler 716 720 { 717 721 private final BufferedOutputStream bos; // needs to be final to be able to synchronize on the shared object 718 722 719 public Synchronized ProcessHandler(BufferedOutputStream bos, int src) {723 public SynchronizedLineByLineHandler(BufferedOutputStream bos, int src) { 720 724 super(src); // will set this.source to STDERR or STDOUT 721 725 this.bos = bos; // caller will close bw, since many more than one 722 // Synchronized ProcessHandlers are using it726 // SynchronizedLineByLineHandlers are using it 723 727 } 724 728 725 729 // 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."; 729 732 730 733 DebugStream.println(msg); // method is already synchronized … … 732 735 SafeProcess.log("*** " + msg, e); 733 736 734 GShell.this.setStatus(GShell.ERROR); 737 GShell.this.setStatus(GShell.ERROR); // synchronized 735 738 } 736 739 … … 740 743 } 741 744 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) { 772 748 fireMessage(GShell.this.type, // not final, needs synchro 773 749 GShell.this.typeAsString(type) + "> " + line,
Note:
See TracChangeset
for help on using the changeset viewer.