Changeset 31707 for main/trunk/gli/src
- Timestamp:
- 2017-05-26T19:43:28+12:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/gli/src/org/greenstone/gatherer/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) { … … 153 153 154 154 /** 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. 155 * If calling this method from a GUI thread when the SafeProcess is in the uninterruptible 156 * phase of natural termination, then this method will return immediately before that phase 157 * has ended. To force the caller to wait until the natural termination phase has ended, 158 * call the other variant of this method with param forceWaitUntilInterruptible set to true: 159 * cancelRunningProcess(true). 160 * @return false if process has already terminated or if it was already terminating when 161 * cancel was called. In such cases no interrupt is sent. 162 * This method returns a boolean that you can call sentInterrupt. 161 163 */ 162 public synchronized boolean cancelRunningProcess() { 164 public boolean cancelRunningProcess() { 165 166 boolean forceWaitUntilInterruptible = true; 167 // by default, event dispatch threads may not want to wait for any joins() taking 168 // place at the time of cancel to be completed. 169 // So don't wait until the SafeProcess becomes interruptible 170 return this.cancelRunningProcess(!forceWaitUntilInterruptible); 171 } 172 173 /** 174 * Call this method when you want to prematurely and safely terminate any process 175 * that SafeProcess may be running. 176 * You may want to implement the SafeProcess.MainHandler interface to write code 177 * for any hooks that will get called during the process' life cycle. 178 * @param forceWaitUntilInterruptible if set to true by a calling GUI thread, then this method 179 * won't return until the running process is interruptible, even if SafeProcess is in the phase 180 * of naturally terminating, upon which no interrupts will be sent to the SafeProcess 181 * thread anyway. The join() calls within SafeProcess.runProcess() are blocking calls and are 182 * therefore sensitive to InterruptedExceptions. But the join() calls are part of the cleanup 183 * phase and shouldn't be interrupted, and nothing thereafter can be interrupted anyway. 184 * This method tends to be called with the param set to false. In that case, if the SafeProcess 185 * is in an uninterruptible phase (as can then only happen during clean up of natural 186 * termination) then a calling GUI thread will just return immediately. Meaning, the GUI thread 187 * won't wait for the SafeProcess thread to finish cleaning up. 188 * @return false if process has already terminated or if it was already terminating when 189 * cancel was called. In such cases no interrupt is sent. 190 * This method returns a boolean that you can call sentInterrupt. 191 */ 192 public synchronized boolean cancelRunningProcess(boolean forceWaitUntilInterruptible) { 163 193 // on interrupt: 164 194 // - forciblyTerminate will be changed to true if the interrupt came in when the process was … … 182 212 // have to wait until afterward 183 213 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 interrupted214 // either way, we can now interrupt the thread that SafeProcess.runProcess() is running in 215 if(this.theProcessThread != null) { // we stored a ref to the main thread that's to be interrupted 186 216 this.theProcessThread.interrupt(); 187 217 log("@@@ Successfully sent interrupt to process."); … … 189 219 } 190 220 } 191 else { // wait for join()s to finish. 221 else { // wait for join()s to finish, if we've been asked to wait 222 192 223 // 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()) { 224 // subsequent to joins() block, so everything thereafter is insensitive to InterruptedExceptions 225 // and everything from the joins() onward are cleanup on natural process termination, so no 226 // interrupt is needed after the joins(). 227 // Still, even if the caller is a GUI thread, they can decide if they want to wait until this 228 // method's end: until the SafeProcess becomes interruptible again 229 230 if(!forceWaitUntilInterruptible && SwingUtilities.isEventDispatchThread()) { 196 231 log("#### Event Dispatch thread, returning"); 197 232 return false; … … 757 792 // but the other suggestion did work: pkill -TERM -P pid did work 758 793 // More reading: 794 // https://superuser.com/questions/343031/sigterm-with-a-keyboard-shortcut 795 // Ctrl-C sends a SIGNINT, not SIGTERM or SIGKILL. And on Ctrl-C, "the signal is sent to the foreground *process group*." 759 796 // https://linux.die.net/man/1/kill (manual) 760 797 // https://unix.stackexchange.com/questions/117227/why-pidof-and-pgrep-are-behaving-differently … … 765 802 766 803 /** 767 * On Unix, will kill the process denoted by processID and any subprocesse dthis launched. Tested on a Mac, where this is used.804 * On Unix, will kill the process denoted by processID and any subprocesses this launched. Tested on a Mac, where this is used. 768 805 * @param force if true will send the -KILL (-9) signal, which may result in abrupt termination without cleanup 769 806 * if false, will send the -TERM (-15) signal, which will allow cleanup before termination. Sending a SIGTERM is preferred. … … 810 847 // the process and its subprocesses (don't need to call this method at all to terminate the processes: the processes 811 848 // 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.");849 log("@@@ Sending termination signal returned exit value 1. On unix this can happen when the process has already been terminated."); 813 850 return true; 814 851 } else {
Note:
See TracChangeset
for help on using the changeset viewer.