Changeset 31702

Show
Ignore:
Timestamp:
25.05.2017 18:09:55 (2 years ago)
Author:
ak19
Message:

1. Correction to previous commit where I'd accidentally attempted a forced KILL request first instead of sending the preferred TERMination request first. The sequence should be the inverse. 2. Adding the command to kill a process tree on linux. We don't seem to need it at present, since an interruption (cancel action) cleanly stops a process and its subprocesses on linux without even requiring a process.destroy() call. But adding the code into SafeProcess?.java for reusability.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • main/trunk/gli/src/org/greenstone/gatherer/util/SafeProcess.java

    r31701 r31702  
    731731     
    732732 
    733 // stackoverflow.com/questions/1835885/send-ctrl-c-to-process-open-by-java   
     733// Can't artificially send Ctrl-C: stackoverflow.com/questions/1835885/send-ctrl-c-to-process-open-by-java 
    734734// (Taskkill command can kill all running perl. But what if we kill perl instances not launched by GS?) 
    735735// stackoverflow.com/questions/912889/how-to-send-interrupt-key-sequence-to-a-java-process 
     
    756756// but the other suggestion did work: pkill -TERM -P pid did work 
    757757// More reading: 
     758// https://linux.die.net/man/1/kill (manual) 
    758759// https://unix.stackexchange.com/questions/117227/why-pidof-and-pgrep-are-behaving-differently 
    759760// https://unix.stackexchange.com/questions/67635/elegantly-get-list-of-children-processes 
    760761// https://stackoverflow.com/questions/994033/mac-os-x-quickest-way-to-kill-quit-an-entire-process-tree-from-within-a-cocoa-a 
    761 // https://unix.stackexchange.com/questions/132224/is-it-possible-to-get-process-group-id-from-procŧŧ 
     762// https://unix.stackexchange.com/questions/132224/is-it-possible-to-get-process-group-id-from-proc 
     763// https://unix.stackexchange.com/questions/99112/default-exit-code-when-process-is-terminated 
    762764 
    763765/** 
     
    766768 * if false, will send the -TERM (-15) signal, which will allow cleanup before termination. Sending a SIGTERM is preferred. 
    767769 * @param killEntireTree if false, will terminate only the process denoted by processID, otherwise all descendants/subprocesses too. 
    768  * @return true if running the kill process returned an exit value of 0  
     770 * @return true if running the kill process returned an exit value of 0 or if it had already been terminated 
    769771*/ 
    770772static boolean killUnixProcessWithID(long processID, boolean force, boolean killEntireTree) { 
     
    773775    String cmd; 
    774776    if(killEntireTree) { // kill the process denoted by processID and any subprocesses this launched 
    775     cmd = "pkill -"+signal + " -P " + processID; // e.g. "pkill -TERM -P pid" 
     777 
     778    if(Utility.isMac()) {  
     779        // this cmd works on Mac (tested Snow Leopard), but on Linux this cmd only terminates toplevel process 
     780        // when doing full-import, and doesn't always terminate subprocesses when doing full-buildcol.pl 
     781        cmd = "pkill -"+signal + " -P " + processID; // e.g. "pkill -TERM -P pid" 
     782    }  
     783    else { // other unix 
     784        // this cmd works on linux, not recognised on Mac (tested Snow Leopard): 
     785        cmd = "kill -"+signal + " -"+processID; // e.g. "kill -TERM -pid" 
     786                                                // note the hyphen before pid to terminate subprocesses too 
     787    } 
     788 
    776789    } else { // kill only the process represented by the processID. 
    777790    cmd = "kill -"+signal + " " + processID; // e.g. "kill -TERM pid" 
     
    780793    SafeProcess proc = new SafeProcess(cmd); 
    781794    int exitValue = proc.runProcess(); 
    782     if(exitValue != 0) { 
    783     log("@@@ Not able to successfull terminate process, got exitvalue " + exitValue); 
    784     log("@@@ Got output " + proc.getStdOutput());  
    785     log("@@@ Got err output " + proc.getStdError()); 
    786     // caller can try again with kill -KILL, by setting force parameter to true 
    787     return false; 
    788     } else { 
     795     
     796     
     797    if(exitValue == 0) { 
    789798    if(force) { 
    790799        log("@@@ Successfully sent SIGKILL to unix process tree rooted at " + processID); 
     
    793802    } 
    794803    return true; 
    795     }     
     804    } else if(!Utility.isMac() && exitValue == 1) { 
     805    // https://stackoverflow.com/questions/28332888/return-value-of-kill 
     806    // "kill returns an exit code of 0 (true) if the process still existed it and was killed. 
     807    // kill returns an exit code of 1 (false) if the kill failed, probably because the process was no longer running." 
     808    // On Linux, interrupting the process and its worker threads and closing resources already successfully terminates 
     809    // the process and its subprocesses (don't need to call this method at all to terminate the processes: the processes 
     810    // aren't running when we get to this method) 
     811    log("@@@ Termination signal returned exitvalue 1, on linux this happens when the process has already been terminated"); 
     812    return true; 
     813    } else { 
     814    log("@@@ Not able to successfully terminate process, got exitvalue " + exitValue); 
     815    log("@@@ Got output: |" + proc.getStdOutput() + "|");  
     816    log("@@@ Got err output: |" + proc.getStdError() + "|"); 
     817    // caller can try again with kill -KILL, by setting force parameter to true 
     818    return false; 
     819    } 
    796820} 
    797821 
     
    803827    log("### in SafeProcess.destroyProcess(Process p)"); 
    804828 
    805     String osName = Utility.getOSdirName(); 
    806  
    807829    // If it isn't windows, process.destroy() terminates any child processes too 
    808     if(osName.equals("linux")) { 
    809     p.destroy(); 
    810     return; 
    811     } 
    812  
    813     if(osName.equals("darwin")) { 
     830    if(!Utility.isWindows()) { 
    814831    long pid = SafeProcess.getProcessID(p); 
    815832    /* 
     
    821838        p.destroy(); // at minimum, will have no effect if the process had already terminated  
    822839    } else { 
    823         boolean forceKill = false; 
     840        boolean forceKill = true; 
    824841        boolean killEntireProcessTree = true; 
     842         
    825843        if(!killUnixProcessWithID(pid, !forceKill, killEntireProcessTree)) { // send sig TERM (kill -15 or kill -TERM) 
    826844        killUnixProcessWithID(pid, forceKill, killEntireProcessTree); // send sig KILL (kill -9 or kill -KILL) 
    827         } 
     845        }        
    828846    } 
    829847