Changeset 31640
- Timestamp:
- 2017-05-01T20:26:27+12:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java
r31631 r31640 10 10 import java.io.OutputStream; 11 11 import java.io.OutputStreamWriter; 12 13 12 import java.util.Arrays; 14 13 15 14 import org.apache.log4j.*; 15 16 //import org.greenstone.gatherer.DebugStream; 16 17 17 18 // Use this class to run a Java Process. It follows the good and safe practices at … … 20 21 21 22 public class SafeProcess { 22 23 //public static int DEBUG = 0; 24 23 25 public static final int STDERR = 0; 24 26 public static final int STDOUT = 1; 25 public static final int STDIN = 2; 27 public static final int STDIN = 2; 28 29 // charset for reading process stderr and stdout streams 30 //public static final String UTF8 = "UTF-8"; 26 31 27 32 static Logger logger = Logger.getLogger(org.greenstone.util.SafeProcess.class.getName()); … … 33 38 private File dir = null; 34 39 private String inputStr = null; 40 private Process process = null; 35 41 36 42 // output from running SafeProcess.runProcess() … … 38 44 private String errorStr = ""; 39 45 private int exitValue = -1; 46 //private String charset = null; 40 47 41 48 // allow callers to process exceptions of the main process thread if they want … … 74 81 public int getExitValue() { return exitValue; } 75 82 76 83 //public void setStreamCharSet(String charset) { this.charset = charset; } 84 77 85 // set any string to send as input to the process spawned by SafeProcess 78 86 public void setInputString(String sendStr) { … … 99 107 100 108 if(this.command != null) { 109 log("SafeProcess running: " + command); 101 110 prcs = rt.exec(this.command); 102 111 } … … 104 113 105 114 // http://stackoverflow.com/questions/5283444/convert-array-of-strings-into-a-string-in-java 106 logger.info("SafeProcess running: " + Arrays.toString(command_args)); 107 //System.err.println("SafeProcess running: " + Arrays.toString(command_args)); 115 log("SafeProcess running: " + Arrays.toString(command_args)); 108 116 109 117 if(this.envp == null) { … … 112 120 113 121 if(this.dir == null) { 114 ///logger.info("\twith: " + Arrays.toString(this.envp)); 115 ///System.err.println("\twith: " + Arrays.toString(this.envp)); 122 //log("\twith: " + Arrays.toString(this.envp)); 116 123 prcs = rt.exec(this.command_args, this.envp); 117 124 } else { 118 ///logger.info("\tfrom directory: " + this.dir); 119 ///logger.info("\twith: " + Arrays.toString(this.envp)); 120 ///System.err.println("\tfrom directory: " + this.dir); 121 ///System.err.println("\twith: " + Arrays.toString(this.envp)); 122 prcs = rt.exec(this.command_args, this.envp, this.dir); 125 //log("\tfrom directory: " + this.dir); 126 //log("\twith: " + Arrays.toString(this.envp)); 127 prcs = rt.exec(this.command_args, this.envp, this.dir); 123 128 } 124 129 } … … 129 134 130 135 // Copied from gli's gui/FormatConversionDialog.java 131 private int waitForWithStreams(Process prcs, 132 SafeProcess.OutputStreamGobbler inputGobbler, 136 private int waitForWithStreams(SafeProcess.OutputStreamGobbler inputGobbler, 133 137 SafeProcess.InputStreamGobbler outputGobbler, 134 138 SafeProcess.InputStreamGobbler errorGobbler) … … 136 140 { 137 141 138 // kick off the stream gobblers 139 inputGobbler.start(); 140 errorGobbler.start(); 141 outputGobbler.start(); 142 143 // any error??? 144 this.exitValue = prcs.waitFor(); // can throw an InterruptedException if process did not terminate 145 146 ///logger.info("Process exitValue: " + exitValue); 147 ///System.err.println("Process exitValue: " + exitValue); 148 142 143 // kick off the stream gobblers 144 inputGobbler.start(); 145 errorGobbler.start(); 146 outputGobbler.start(); 147 148 // any error??? 149 try { 150 this.exitValue = process.waitFor(); // can throw an InterruptedException if process did not terminate 151 } catch(InterruptedException ie) { 152 log("*** Process interrupted (InterruptedException). Expected to be a Cancel operation."); 153 // don't print stacktrace: an interrupt here is not an error, it's expected to be a cancel action 154 if(exceptionHandler != null) { 155 exceptionHandler.gotException(ie); 156 } 157 158 // propagate interrupts to worker threads here 159 // unless the interrupt emanated from any of them in any join(), 160 // which will be caught by caller's catch on InterruptedException. 161 // Only if the thread that SafeProcess runs in was interrupted 162 // should we propagate the interrupt to the worker threads. 163 // http://stackoverflow.com/questions/2126997/who-is-calling-the-java-thread-interrupt-method-if-im-not 164 // "I know that in JCiP it is mentioned that you should never interrupt threads you do not own" 165 // But SafeProcess owns the worker threads, so it has every right to interrupt them 166 // Also read http://stackoverflow.com/questions/13623445/future-cancel-method-is-not-working?noredirect=1&lq=1 167 168 // http://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java 169 // http://stackoverflow.com/questions/4906799/why-invoke-thread-currentthread-interrupt-when-catch-any-interruptexception 170 // "Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests." 171 // Does that mean that since this code implements this thread's interruption policy, it's ok 172 // to swallow the interrupt this time and not let it propagate by commenting out the next line? 173 //Thread.currentThread().interrupt(); // re-interrupt the thread 174 175 inputGobbler.interrupt(); 176 errorGobbler.interrupt(); 177 outputGobbler.interrupt(); 178 179 // even after the interrupts, we want to proceed to calling join() on all the worker threads 180 // in order to wait for each of them to die before attempting to destroy the process if it 181 // still hasn't terminated after all that. 182 } finally { 183 184 //log("Process exitValue: " + exitValue); 185 149 186 // From the comments of 150 187 // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 … … 152 189 // if there's no waiting for the threads, call join() on each Thread (StreamGobbler) object. 153 190 // From Thread API: join() "Waits for this thread (the thread join() is invoked on) to die." 191 192 // Wait for each of the threads to die, before attempting to destroy the process 193 // Any of these can throw InterruptedExceptions too 194 // and will be processed by the calling function's catch on InterruptedException. 195 // However, no one besides us will interrupting these threads I think... 196 // and we won't be throwing the InterruptedException from within the threads... 197 // So if any streamgobbler.join() call throws an InterruptedException, that would be unexpected 198 154 199 outputGobbler.join(); 155 200 errorGobbler.join(); 156 inputGobbler.join(); 157 158 159 // set the variables th e code thatcreated a SafeProcess object may want to inspect201 inputGobbler.join(); 202 203 204 // set the variables that the code which created a SafeProcess object may want to inspect 160 205 this.outputStr = outputGobbler.getOutput(); 161 206 this.errorStr = errorGobbler.getOutput(); … … 163 208 // Since we didn't have an exception, process should have terminated now (waitFor blocks until then) 164 209 // Set process to null so we don't forcibly terminate it below with process.destroy() 165 prcs = null; 166 167 return this.exitValue; 168 } 169 210 this.process = null; 211 } 212 213 // Don't return from finally, it's considered an abrupt completion and exceptions are lost, see 214 // http://stackoverflow.com/questions/18205493/can-we-use-return-in-finally-block 215 return this.exitValue; 216 } 217 218 219 public synchronized boolean processRunning() { 220 if(process == null) return false; 221 return SafeProcess.processRunning(this.process); 222 } 170 223 171 224 // Run a very basic process: with no reading from or writing to the Process' iostreams, 172 225 // this just execs the process and waits for it to return 173 226 public int runBasicProcess() { 174 Process prcs = null;175 227 try { 176 228 // 1. create the process 177 pr cs = doRuntimeExec();229 process = doRuntimeExec(); 178 230 // 2. basic waitFor the process to finish 179 this.exitValue = pr cs.waitFor();231 this.exitValue = process.waitFor(); 180 232 181 233 … … 184 236 exceptionHandler.gotException(ioe); 185 237 } else { 186 logger.error("IOException: " + ioe.getMessage(), ioe); 187 //System.err.println("IOException " + ioe.getMessage()); 188 //ioe.printStackTrace(); 238 log("IOException: " + ioe.getMessage(), ioe); 189 239 } 190 240 } catch(InterruptedException ie) { … … 192 242 if(exceptionHandler != null) { 193 243 exceptionHandler.gotException(ie); 194 } else { 195 logger.error("Process InterruptedException: " + ie.getMessage(), ie); 196 //System.err.println("Process InterruptedException " + ie.getMessage()); 197 ///ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 244 } else { // Unexpected InterruptedException, so printstacktrace 245 log("Process InterruptedException: " + ie.getMessage(), ie); 198 246 } 199 247 … … 201 249 } finally { 202 250 203 if( pr cs != null ) {204 pr cs.destroy(); // see runProcess() below251 if( process != null ) { 252 process.destroy(); // see runProcess() below 205 253 } 206 254 } … … 220 268 CustomProcessHandler procErrHandler) 221 269 { 222 Process prcs = null;223 270 SafeProcess.OutputStreamGobbler inputGobbler = null; 224 271 SafeProcess.InputStreamGobbler errorGobbler = null; … … 227 274 try { 228 275 // 1. get the Process object 229 pr cs = doRuntimeExec();276 process = doRuntimeExec(); 230 277 231 278 … … 236 283 // send inputStr to process. The following constructor can handle inputStr being null 237 284 inputGobbler = // WriterToProcessInputStream 238 new SafeProcess.OutputStreamGobbler(pr cs.getOutputStream(), this.inputStr);285 new SafeProcess.OutputStreamGobbler(process.getOutputStream(), this.inputStr); 239 286 } else { // user will do custom handling of process' InputStream 240 inputGobbler = new SafeProcess.OutputStreamGobbler(pr cs.getOutputStream(), procInHandler);287 inputGobbler = new SafeProcess.OutputStreamGobbler(process.getOutputStream(), procInHandler); 241 288 } 242 289 … … 244 291 if(procErrHandler == null) { 245 292 errorGobbler // ReaderFromProcessOutputStream 246 = new SafeProcess.InputStreamGobbler(pr cs.getErrorStream(), splitStdErrorNewLines);293 = new SafeProcess.InputStreamGobbler(process.getErrorStream(), splitStdErrorNewLines); 247 294 } else { 248 295 errorGobbler 249 = new SafeProcess.InputStreamGobbler(pr cs.getErrorStream(), procErrHandler);296 = new SafeProcess.InputStreamGobbler(process.getErrorStream(), procErrHandler); 250 297 } 251 298 … … 253 300 if(procOutHandler == null) { 254 301 outputGobbler 255 = new SafeProcess.InputStreamGobbler(pr cs.getInputStream(), splitStdOutputNewLines);302 = new SafeProcess.InputStreamGobbler(process.getInputStream(), splitStdOutputNewLines); 256 303 } else { 257 304 outputGobbler 258 = new SafeProcess.InputStreamGobbler(pr cs.getInputStream(), procOutHandler);305 = new SafeProcess.InputStreamGobbler(process.getInputStream(), procOutHandler); 259 306 } 260 307 261 308 262 309 // 3. kick off the stream gobblers 263 this.exitValue = waitForWithStreams( prcs,inputGobbler, outputGobbler, errorGobbler);310 this.exitValue = waitForWithStreams(inputGobbler, outputGobbler, errorGobbler); 264 311 265 312 } catch(IOException ioe) { … … 267 314 exceptionHandler.gotException(ioe); 268 315 } else { 269 logger.error("IOexception: " + ioe.getMessage(), ioe); 270 //System.err.println("IOexception " + ioe.getMessage()); 271 //ioe.printStackTrace(); 272 } 273 } catch(InterruptedException ie) { 274 316 log("IOexception: " + ioe.getMessage(), ioe); 317 } 318 } catch(InterruptedException ie) { // caused during any of the gobblers.join() calls, this is unexpected so print stack trace 319 275 320 if(exceptionHandler != null) { 276 321 exceptionHandler.gotException(ie); 322 log("@@@@ Unexpected InterruptedException when waiting for process stream gobblers to die"); 277 323 } else { 278 logger.error("Process InterruptedException: " + ie.getMessage(), ie); 279 //System.err.println("Process InterruptedException " + ie.getMessage()); 280 ///ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 281 } 282 283 // propagate interrupts to worker threads here? 284 // unless the interrupt emanated from any of them in any join()... 285 // Only if the thread SafeProcess runs in was interrupted 286 // do we propagate the interrupt to the worker threads. 287 // http://stackoverflow.com/questions/2126997/who-is-calling-the-java-thread-interrupt-method-if-im-not 288 // "I know that in JCiP it is mentioned that you should never interrupt threads you do not own" 289 // But SafeProcess owns the worker threads, so it have every right to interrupt them 290 // Also read http://stackoverflow.com/questions/13623445/future-cancel-method-is-not-working?noredirect=1&lq=1 291 if(Thread.currentThread().isInterrupted()) { 292 inputGobbler.interrupt(); 293 errorGobbler.interrupt(); 294 outputGobbler.interrupt(); 295 } 296 297 // On catchingInterruptedException, re-interrupt the thread. 298 // This is just how InterruptedExceptions tend to be handled 299 // See also http://stackoverflow.com/questions/4906799/why-invoke-thread-currentthread-interrupt-when-catch-any-interruptexception 300 // and https://praveer09.github.io/technology/2015/12/06/understanding-thread-interruption-in-java/ 301 302 // http://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java 303 // http://stackoverflow.com/questions/4906799/why-invoke-thread-currentthread-interrupt-when-catch-any-interruptexception 304 // "Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests." 305 // Does that mean that since this code implements this thread's interruption policy, it's ok 306 // to swallow the interrupt this time and not let it propagate by commenting out the next line? 307 Thread.currentThread().interrupt(); // re-interrupt the thread - which thread? Infinite loop? 324 log("*** Unexpected InterruptException when waiting for process stream gobblers to die:" + ie.getMessage(), ie); 325 } 326 327 // see comments in other runProcess() 328 Thread.currentThread().interrupt(); 329 308 330 } finally { 309 310 // Moved into here from GS2PerlConstructor which said 311 // "I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine." 312 // http://steveliles.github.io/invoking_processes_from_java.html 313 // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 314 // http://mark.koli.ch/leaky-pipes-remember-to-close-your-streams-when-using-javas-runtimegetruntimeexec 315 if( prcs != null ) { 316 prcs.destroy(); 317 } 331 //String cmd = (this.command == null) ? Arrays.toString(this.command_args) : this.command; 332 //log("*** In finally of SafeProcess.runProcess(3 params): " + cmd); 333 334 if( process != null ) { 335 log("*** Going to call process.destroy 2"); 336 process.destroy(); 337 process = null; 338 log("*** Have called process.destroy 2"); 339 } 340 318 341 } 319 342 … … 323 346 public int runProcess(LineByLineHandler outLineByLineHandler, LineByLineHandler errLineByLineHandler) 324 347 { 325 Process prcs = null;326 348 SafeProcess.OutputStreamGobbler inputGobbler = null; 327 349 SafeProcess.InputStreamGobbler errorGobbler = null; … … 330 352 try { 331 353 // 1. get the Process object 332 pr cs = doRuntimeExec();354 process = doRuntimeExec(); 333 355 334 356 … … 338 360 // send inputStr to process. The following constructor can handle inputStr being null 339 361 inputGobbler = // WriterToProcessInputStream 340 new SafeProcess.OutputStreamGobbler(pr cs.getOutputStream(), this.inputStr);362 new SafeProcess.OutputStreamGobbler(process.getOutputStream(), this.inputStr); 341 363 342 364 // PROC ERR STREAM to monitor for any error messages or expected output in the process' stderr 343 365 errorGobbler // ReaderFromProcessOutputStream 344 = new SafeProcess.InputStreamGobbler(pr cs.getErrorStream(), splitStdErrorNewLines);366 = new SafeProcess.InputStreamGobbler(process.getErrorStream(), splitStdErrorNewLines); 345 367 // PROC OUT STREAM to monitor for the expected std output line(s) 346 368 outputGobbler 347 = new SafeProcess.InputStreamGobbler(pr cs.getInputStream(), splitStdOutputNewLines);369 = new SafeProcess.InputStreamGobbler(process.getInputStream(), splitStdOutputNewLines); 348 370 349 371 … … 358 380 359 381 // 4. kick off the stream gobblers 360 this.exitValue = waitForWithStreams( prcs,inputGobbler, outputGobbler, errorGobbler);382 this.exitValue = waitForWithStreams(inputGobbler, outputGobbler, errorGobbler); 361 383 362 384 } catch(IOException ioe) { … … 364 386 exceptionHandler.gotException(ioe); 365 387 } else { 366 logger.error("IOexception: " + ioe.getMessage(), ioe); 367 //System.err.println("IOexception " + ioe.getMessage()); 368 //ioe.printStackTrace(); 369 } 370 } catch(InterruptedException ie) { 371 388 log("IOexception: " + ioe.getMessage(), ioe); 389 } 390 } catch(InterruptedException ie) { // caused during any of the gobblers.join() calls, this is unexpected so log it 391 372 392 if(exceptionHandler != null) { 373 393 exceptionHandler.gotException(ie); 394 log("@@@@ Unexpected InterruptedException when waiting for process stream gobblers to die"); 374 395 } else { 375 logger.error("Process InterruptedException: " + ie.getMessage(), ie); 376 //System.err.println("Process InterruptedException " + ie.getMessage()); 377 ///ie.printStackTrace(); // an interrupt here is not an error, it can be a cancel action 378 } 379 380 // propagate interrupts to worker threads here? 381 // unless the interrupt emanated from any of them in any join()... 382 // Only if the thread SafeProcess runs in was interrupted 383 // do we propagate the interrupt to the worker threads. 384 // http://stackoverflow.com/questions/2126997/who-is-calling-the-java-thread-interrupt-method-if-im-not 385 // "I know that in JCiP it is mentioned that you should never interrupt threads you do not own" 386 // But SafeProcess owns the worker threads, so it have every right to interrupt them 387 // Also read http://stackoverflow.com/questions/13623445/future-cancel-method-is-not-working?noredirect=1&lq=1 388 if(Thread.currentThread().isInterrupted()) { 389 inputGobbler.interrupt(); 390 errorGobbler.interrupt(); 391 outputGobbler.interrupt(); 392 } 393 394 // On catchingInterruptedException, re-interrupt the thread. 396 log("*** Unexpected InterruptException when waiting for process stream gobblers to die: " + ie.getMessage(), ie); 397 } 398 // We're not causing any interruptions that may occur when trying to stop the worker threads 399 // So resort to default behaviour in this catch? 400 // "On catching InterruptedException, re-interrupt the thread." 395 401 // This is just how InterruptedExceptions tend to be handled 396 402 // See also http://stackoverflow.com/questions/4906799/why-invoke-thread-currentthread-interrupt-when-catch-any-interruptexception 397 403 // and https://praveer09.github.io/technology/2015/12/06/understanding-thread-interruption-in-java/ 398 399 // http://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java400 // http://stackoverflow.com/questions/4906799/why-invoke-thread-currentthread-interrupt-when-catch-any-interruptexception401 // "Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests."402 // Does that mean that since this code implements this thread's interruption policy, it's ok403 // to swallow the interrupt this time and not let it propagate by commenting out the next line?404 404 Thread.currentThread().interrupt(); // re-interrupt the thread - which thread? Infinite loop? 405 405 406 } finally { 406 407 407 // Moved into here from GS2PerlConstructor which said408 // "I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine ."408 // Moved into here from GS2PerlConstructor and GShell.runLocal() which said 409 // "I need to somehow kill the child process. Unfortunately Thread.stop() and Process.destroy() both fail to do this. But now, thankx to the magic of Michaels 'close the stream suggestion', it works fine (no it doesn't!)" 409 410 // http://steveliles.github.io/invoking_processes_from_java.html 410 411 // http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 411 412 // http://mark.koli.ch/leaky-pipes-remember-to-close-your-streams-when-using-javas-runtimegetruntimeexec 412 if( prcs != null ) { 413 prcs.destroy(); 413 414 //String cmd = (this.command == null) ? Arrays.toString(this.command_args) : this.command; 415 //log("*** In finally of SafeProcess.runProcess(2 params): " + cmd); 416 417 if( process != null ) { 418 log("*** Going to call process.destroy 1"); 419 process.destroy(); 420 process = null; 421 log("*** Have called process.destroy 1"); 414 422 } 415 423 } … … 451 459 this.source = src; // STDERR or STDOUT or STDIN 452 460 } 461 462 public String getThreadNamePrefix() { 463 return SafeProcess.streamToString(this.source); 464 } 453 465 454 466 public abstract void run(Closeable stream); //InputStream or OutputStream … … 465 477 } 466 478 479 public String getThreadNamePrefix() { 480 return SafeProcess.streamToString(this.source); 481 } 482 467 483 public abstract void gotLine(String line); // first non-null line 468 484 public abstract void gotException(Exception e); // for when an exception occurs instead of getting a line 469 485 } 486 470 487 471 488 //**************** StreamGobbler Inner class definitions (stream gobblers copied from GLI) **********// … … 482 499 private LineByLineHandler lineByLineHandler = null; 483 500 501 protected InputStreamGobbler() { 502 super("InputStreamGobbler"); 503 } 504 484 505 public InputStreamGobbler(InputStream is) 485 506 { 507 this(); // sets thread name 486 508 this.is = is; 487 509 this.split_newlines = false; … … 490 512 public InputStreamGobbler(InputStream is, boolean split_newlines) 491 513 { 514 this(); // sets thread name 492 515 this.is = is; 493 516 this.split_newlines = split_newlines; … … 496 519 public InputStreamGobbler(InputStream is, CustomProcessHandler customHandler) 497 520 { 521 this(); // thread name 498 522 this.is = is; 499 523 this.customHandler = customHandler; 524 this.adjustThreadName(customHandler.getThreadNamePrefix()); 525 } 526 527 528 private void adjustThreadName(String prefix) { 529 this.setName(prefix + this.getName()); 500 530 } 501 531 502 532 public void setLineByLineHandler(LineByLineHandler lblHandler) { 503 533 this.lineByLineHandler = lblHandler; 534 this.adjustThreadName(lblHandler.getThreadNamePrefix()); 504 535 } 505 536 … … 511 542 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); 512 543 String line=null; 513 while ( (line = br.readLine()) != null ) { 514 515 if(this.isInterrupted()) { // should we not instead check if SafeProcess thread was interrupted? 516 logger.info("Got interrupted when reading lines from process err/out stream."); 517 //System.err.println("InputStreamGobbler.runDefault() Got interrupted when reading lines from process err/out stream."); 518 break; // will go to finally block 519 } 520 521 //System.out.println("@@@ GOT LINE: " + line); 544 while ( !this.isInterrupted() && (line = br.readLine()) != null ) { 545 546 //log("@@@ GOT LINE: " + line); 522 547 outputstr.append(line); 523 548 if(split_newlines) { … … 529 554 } 530 555 } 556 531 557 } catch (IOException ioe) { 532 558 if(lineByLineHandler != null) { 533 559 lineByLineHandler.gotException(ioe); 534 560 } else { 535 logger.error("Exception when reading from a process' stdout/stderr stream: ", ioe); 536 //System.err.println("Exception when reading from a process' stdout/stderr stream: "); 537 //ioe.printStackTrace(); 561 log("Exception when reading process stream with " + this.getName() + ": ", ioe); 538 562 } 539 563 } finally { 564 if(this.isInterrupted()) { 565 log("@@@ Successfully interrupted " + this.getName() + "."); 566 } 540 567 SafeProcess.closeResource(br); 541 568 } … … 569 596 private CustomProcessHandler customHandler = null; 570 597 598 protected OutputStreamGobbler() { 599 super("stdinOutputStreamGobbler"); // thread name 600 } 601 571 602 public OutputStreamGobbler(OutputStream os) { 603 this(); // set thread name 572 604 this.os = os; 573 605 } … … 575 607 public OutputStreamGobbler(OutputStream os, String inputstr) 576 608 { 609 this(); // set thread name 577 610 this.os = os; 578 611 this.inputstr = inputstr; … … 580 613 581 614 public OutputStreamGobbler(OutputStream os, CustomProcessHandler customHandler) { 615 this(); // set thread name 582 616 this.os = os; 583 617 this.customHandler = customHandler; … … 589 623 if (inputstr == null) { 590 624 return; 625 } 626 627 // also quit if the process was interrupted before we could send anything to its stdin 628 if(this.isInterrupted()) { 629 log(this.getName() + " thread was interrupted."); 630 return; 591 631 } 592 632 … … 612 652 */ 613 653 } catch (IOException ioe) { 614 logger.error("Exception writing to SafeProcess' inputstream: ", ioe); 615 //System.err.println("Exception writing to SafeProcess' inputstream: "); 616 //ioe.printStackTrace(); 654 log("Exception writing to SafeProcess' inputstream: ", ioe); 617 655 } finally { 618 656 SafeProcess.closeResource(osw); … … 632 670 runCustom(); 633 671 } 634 635 672 } 636 673 } // end static inner class OutputStreamGobbler 637 674 675 //**************** Static methods **************// 676 677 678 // logger and DebugStream print commands are synchronized, therefore thread safe. 679 public static void log(String msg) { 680 logger.info(msg); 681 682 //System.err.println(msg); 683 684 //DebugStream.println(msg); 685 } 686 687 public static void log(String msg, Exception e) { // Print stack trace on the exception 688 logger.error(msg, e); 689 690 //System.err.println(msg); 691 //e.printStackTrace(); 692 693 //DebugStream.println(msg); 694 //DebugStream.printStackTrace(e); 695 } 696 697 public static void log(Exception e) { 698 logger.error(e); 699 700 //e.printStackTrace(); 701 702 //DebugStream.printStackTrace(e); 703 } 704 705 public static void log(String msg, Exception e, boolean printStackTrace) { 706 if(printStackTrace) { 707 log(msg, e); 708 } else { 709 log(msg); 710 } 711 } 712 713 public static String streamToString(int src) { 714 String stream; 715 switch(src) { 716 case STDERR: 717 stream = "stderr"; 718 break; 719 case STDOUT: 720 stream = "stdout"; 721 break; 722 default: 723 stream = "stdin"; 724 } 725 return stream; 726 } 638 727 639 728 //**************** Useful static methods. Copied from GLI's Utility.java ****************** … … 651 740 } 652 741 } catch(Exception e) { 653 logger.error("Exception closing resource: ", e); 654 //System.err.println("Exception closing resource: " + e.getMessage()); 655 //e.printStackTrace(); 742 log("Exception closing resource: " + e.getMessage(), e); 656 743 resourceHandle = null; 657 744 success = false; … … 672 759 } 673 760 761 // Moved from GShell.java 762 /** Determine if the given process is still executing. It does this by attempting to throw an exception - not the most efficient way, but the only one as far as I know 763 * @param process the Process to test 764 * @return true if it is still executing, false otherwise 765 */ 766 static public boolean processRunning(Process process) { 767 boolean process_running = false; 768 769 try { 770 process.exitValue(); // This will throw an exception if the process hasn't ended yet. 771 } 772 catch(IllegalThreadStateException itse) { 773 process_running = true; 774 } 775 catch(Exception exception) { 776 log(exception); // DebugStream.printStackTrace(exception); 777 } 778 return process_running; 779 } 780 674 781 } // end class SafeProcess
Note:
See TracChangeset
for help on using the changeset viewer.