Changeset 31703 for main/trunk/gli

Show
Ignore:
Timestamp:
25.05.2017 18:47:14 (2 years ago)
Author:
ak19
Message:

When an instance of SafeProcess? calls its static destroyProcess method, this happens on cancel action which would have caused an Interrupt to the SafeProcess? thread that interrupts the worker threads, all of which cleanly tidy up after themselves. On Linux, this has the effect that the Process internal to SafeProcess?, and any subprocesses that the process may have launched, are all neatly terminated. So on Linux, when destroyProcess is called by a SafeProcess? instance on itself, there's no need to send a SIGTERM (else SIGKILL) to terminate the Process, as it's already cleanly terminated. Reducing the overkill step in such a scenario. The public static SafeProcess?.destroyProcess(Process p) now forces the step of sending a termination signal, since any caller outside a SafeProcess? instance won't neatly tidy up their Process object with interrupts.

Files:
1 modified

Legend:

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

    r31702 r31703  
    609609 
    610610        if(mainHandler != null) mainHandler.beforeProcessDestroy(); 
    611         SafeProcess.destroyProcess(process); // see runProcess(2 args/3 args) 
     611        boolean noNeedToDestroyIfOnLinux = true; // Interrupt handling suffices to cleanup process and subprocesses on Linux 
     612        SafeProcess.destroyProcess(process, noNeedToDestroyIfOnLinux); // see runProcess(2 args/3 args) 
    612613        if(mainHandler != null) mainHandler.afterProcessDestroy(); 
    613614 
     
    809810    // the process and its subprocesses (don't need to call this method at all to terminate the processes: the processes 
    810811    // 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    log("@@@ Sending termination signal returned exit value 1. On linux this happens when the process has already been terminated"); 
    812813    return true; 
    813814    } else { 
     
    820821} 
    821822 
     823public static void destroyProcess(Process p) { 
     824    // A cancel action results in an interruption to the process thread, which in turn interrupts 
     825    // the SafeProcess' worker threads, all which clean up after themselves. 
     826    // On linux, this suffices to cleanly terminate a Process and any subprocesses that may have launched 
     827    // so we don't need to do extra work in such a case. But the interrupts happen only when SafeProcess calls 
     828    // destroyProcess() on the Process it was running internally, and not if anyone else tries to end a  
     829    // Process by calling SafeProcess.destroyProcess(p). In such cases, the Process needs to be actively terminated: 
     830    boolean canSkipExtraWorkIfLinux = true; 
     831    SafeProcess.destroyProcess(p, !canSkipExtraWorkIfLinux); 
     832} 
    822833 
    823834// On linux and mac, p.destroy() suffices to kill processes launched by p as well. 
    824835// On Windows we need to do more work, since otherwise processes launched by p remain around executing until they naturally terminate. 
    825836// e.g. full-import.pl may be terminated with p.destroy(), but it launches import.pl which is left running until it naturally terminates. 
    826 public static void destroyProcess(Process p) { 
     837private static void destroyProcess(Process p, boolean canSkipExtraWorkIfLinux) { 
    827838    log("### in SafeProcess.destroyProcess(Process p)"); 
    828839 
    829840    // If it isn't windows, process.destroy() terminates any child processes too 
    830     if(!Utility.isWindows()) { 
     841    if(Utility.isWindows()) { 
     842     
     843    if(!SafeProcess.isAvailable("wmic")) { 
     844        log("wmic, used to kill subprocesses, is not available. Unable to terminate subprocesses..."); 
     845        log("Kill them manually from the TaskManager or they will proceed to run to termination"); 
     846         
     847        // At least we can get rid of the top level process we launched 
     848        p.destroy(); 
     849        return; 
     850    }    
     851     
     852    // get the process id of the process we launched, 
     853    // so we can use it to find the pids of any subprocesses it launched in order to terminate those too. 
     854     
     855    long processID = SafeProcess.getProcessID(p); 
     856    if(processID == -1) { // the process doesn't exist or no longer exists (terminated naturally?) 
     857        p.destroy(); // minimum step, do this anyway, at worst there's no process and this won't have any effect 
     858    } else { 
     859        log("Attempting to terminate sub processes of Windows process with pid " + processID); 
     860        terminateSubProcessesRecursively(processID, p); 
     861    } 
     862    return; 
     863     
     864    } 
     865    else { // linux or mac 
     866 
     867    // if we're on linux and would have already terminated by now (in which case canSkipExtraWorkForLinux would be true), 
     868    // then there's nothing much left to do. This would only be the case if SafeProcess is calling this method on its 
     869    // internal process, since it would have successfully cleaned up on Interruption and there would be no process left running 
     870    if(!Utility.isMac() && canSkipExtraWorkIfLinux) { 
     871        log("@@@ Linux: Cancelling a SafeProcess instance does not require any complicated system destroy operation"); 
     872        p.destroy(); // vestigial: this will have no effect if the process had already terminated, which is the case in this block 
     873        return; 
     874    } 
     875    // else we're on a Mac or an external caller (not SafeProcess) has requested explicit termination on Linux 
     876     
    831877    long pid = SafeProcess.getProcessID(p); 
    832878    /* 
     
    845891        }        
    846892    } 
    847  
     893     
    848894    return; 
    849895    } 
     
    851897    // else we're on windows: 
    852898 
    853     if(!SafeProcess.isAvailable("wmic")) { 
    854     log("wmic, used to kill subprocesses, is not available. Unable to terminate subprocesses..."); 
    855     log("Kill them manually from the TaskManager or they will proceed to run to termination"); 
    856      
    857     // At least we can get rid of the top level process we launched 
    858     p.destroy(); 
    859     return; 
    860     }    
    861      
    862     // get the process id of the process we launched, 
    863     // so we can use it to find the pids of any subprocesses it launched in order to terminate those too. 
    864      
    865     long processID = SafeProcess.getProcessID(p); 
    866     if(processID == -1) { // the process doesn't exist or no longer exists (terminated naturally?) 
    867     p.destroy(); // minimum step, do this anyway, at worst there's no process and this won't have any effect 
    868     } else { 
    869     log("Attempting to terminate sub processes of Windows process with pid " + processID); 
    870     terminateSubProcessesRecursively(processID, p); 
    871     } 
    872899     
    873900}