Changeset 31702 for main/trunk/gli/src


Ignore:
Timestamp:
2017-05-25T18:09:55+12:00 (7 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.
File:
1 edited

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
Note: See TracChangeset for help on using the changeset viewer.