- Timestamp:
- 2017-05-26T19:43:28+12:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/util/SafeProcess.java
r31706 r31707 43 43 public static String WIN_KILL_CMD; 44 44 45 46 47 48 49 50 45 /** 46 * Boolean interruptible is used to mark any sections of blocking code that should not be interrupted 47 * with an InterruptedExceptions. At present only the cancelRunningProcess() attempts to do such a thing 48 * and avoids doing so when interruptible is false. 49 * Note that interruptible is also used as a lock, so remember to synchronize on it when using it! 50 */ 51 51 public Boolean interruptible = Boolean.TRUE; 52 52 … … 76 76 // allow callers to process exceptions of the main process thread if they want 77 77 private ExceptionHandler exceptionHandler = null; 78 79 80 78 /** allow callers to implement hooks that get called during the main phases of the internal 79 * process' life cycle, such as before and after process.destroy() gets called 80 */ 81 81 private MainProcessHandler mainHandler = null; 82 82 … … 127 127 128 128 /** to set a handler that will handle the main (SafeProcess) thread, 129 129 * implementing the hooks that will get called during the internal process' life cycle, 130 130 * such as before and after process.destroy() is called */ 131 131 public void setMainHandler(MainProcessHandler handler) { … … 152 152 */ 153 153 154 154 155 /** 155 * Call this method when you want to prematurely and safely terminate any process 156 * that SafeProcess may be running. 157 * You may want to implement the SafeProcess.MainHandler interface to write code 158 * for any hooks that will get called during the process' life cycle. 159 * @return false if process has already terminated or if it was already terminating 160 * when cancel was called. In such cases no interrupt is sent. Returns boolean sentInterrupt. 156 * If calling this method from a GUI thread when the SafeProcess is in the uninterruptible 157 * phase of natural termination, then this method will return immediately before that phase 158 * has ended. To force the caller to wait until the natural termination phase has ended, 159 * call the other variant of this method with param forceWaitUntilInterruptible set to true: 160 * cancelRunningProcess(true). 161 * @return false if process has already terminated or if it was already terminating when 162 * cancel was called. In such cases no interrupt is sent. 163 * This method returns a boolean that you can call sentInterrupt. 161 164 */ 162 public synchronized boolean cancelRunningProcess() { 165 public boolean cancelRunningProcess() { 166 167 boolean forceWaitUntilInterruptible = true; 168 // by default, event dispatch threads may not want to wait for any joins() taking 169 // place at the time of cancel to be completed. 170 // So don't wait until the SafeProcess becomes interruptible 171 return this.cancelRunningProcess(!forceWaitUntilInterruptible); 172 } 173 174 /** 175 * Call this method when you want to prematurely and safely terminate any process 176 * that SafeProcess may be running. 177 * You may want to implement the SafeProcess.MainHandler interface to write code 178 * for any hooks that will get called during the process' life cycle. 179 * @param forceWaitUntilInterruptible if set to true by a calling GUI thread, then this method 180 * won't return until the running process is interruptible, even if SafeProcess is in the phase 181 * of naturally terminating, upon which no interrupts will be sent to the SafeProcess 182 * thread anyway. The join() calls within SafeProcess.runProcess() are blocking calls and are 183 * therefore sensitive to InterruptedExceptions. But the join() calls are part of the cleanup 184 * phase and shouldn't be interrupted, and nothing thereafter can be interrupted anyway. 185 * This method tends to be called with the param set to false. In that case, if the SafeProcess 186 * is in an uninterruptible phase (as can then only happen during clean up of natural 187 * termination) then a calling GUI thread will just return immediately. Meaning, the GUI thread 188 * won't wait for the SafeProcess thread to finish cleaning up. 189 * @return false if process has already terminated or if it was already terminating when 190 * cancel was called. In such cases no interrupt is sent. 191 * This method returns a boolean that you can call sentInterrupt. 192 */ 193 public synchronized boolean cancelRunningProcess(boolean forceWaitUntilInterruptible) { 163 194 // on interrupt: 164 195 // - forciblyTerminate will be changed to true if the interrupt came in when the process was … … 182 213 // have to wait until afterward 183 214 if (interruptible) { 184 // either way, we can now interrupt the thread - if we have one (we should)185 if(this.theProcessThread != null) { // we 're told which thread shouldbe interrupted215 // either way, we can now interrupt the thread that SafeProcess.runProcess() is running in 216 if(this.theProcessThread != null) { // we stored a ref to the main thread that's to be interrupted 186 217 this.theProcessThread.interrupt(); 187 218 log("@@@ Successfully sent interrupt to process."); … … 189 220 } 190 221 } 191 else { // wait for join()s to finish. 222 else { // wait for join()s to finish, if we've been asked to wait 223 192 224 // During and after joining(), there's no need to interrupt any more anyway: no calls 193 // subsequent to joins() block, so everything thereafter is insensitive to InterruptedExceptions. 194 195 if(SwingUtilities.isEventDispatchThread()) { 225 // subsequent to joins() block, so everything thereafter is insensitive to InterruptedExceptions 226 // and everything from the joins() onward are cleanup on natural process termination, so no 227 // interrupt is needed after the joins(). 228 // Still, even if the caller is a GUI thread, they can decide if they want to wait until this 229 // method's end: until the SafeProcess becomes interruptible again 230 231 if(!forceWaitUntilInterruptible && SwingUtilities.isEventDispatchThread()) { 196 232 log("#### Event Dispatch thread, returning"); 197 233 return false; … … 757 793 // but the other suggestion did work: pkill -TERM -P pid did work 758 794 // More reading: 795 // https://superuser.com/questions/343031/sigterm-with-a-keyboard-shortcut 796 // Ctrl-C sends a SIGNINT, not SIGTERM or SIGKILL. And on Ctrl-C, "the signal is sent to the foreground *process group*." 759 797 // https://linux.die.net/man/1/kill (manual) 760 798 // https://unix.stackexchange.com/questions/117227/why-pidof-and-pgrep-are-behaving-differently … … 765 803 766 804 /** 767 * On Unix, will kill the process denoted by processID and any subprocesse dthis launched. Tested on a Mac, where this is used.805 * On Unix, will kill the process denoted by processID and any subprocesses this launched. Tested on a Mac, where this is used. 768 806 * @param force if true will send the -KILL (-9) signal, which may result in abrupt termination without cleanup 769 807 * if false, will send the -TERM (-15) signal, which will allow cleanup before termination. Sending a SIGTERM is preferred. … … 810 848 // the process and its subprocesses (don't need to call this method at all to terminate the processes: the processes 811 849 // aren't running when we get to this method) 812 log("@@@ Sending termination signal returned exit value 1. On unix this happenswhen the process has already been terminated.");850 log("@@@ Sending termination signal returned exit value 1. On unix this can happen when the process has already been terminated."); 813 851 return true; 814 852 } else {
Note:
See TracChangeset
for help on using the changeset viewer.