Index: main/trunk/gli/src/org/greenstone/gatherer/util/SafeProcess.java
===================================================================
--- main/trunk/gli/src/org/greenstone/gatherer/util/SafeProcess.java	(revision 31650)
+++ main/trunk/gli/src/org/greenstone/gatherer/util/SafeProcess.java	(revision 31651)
@@ -38,6 +38,6 @@
     public static final int STDOUT = 1;
     public static final int STDIN = 2;
-	// can't make this variable final and init in a static block, because it needs to use other SafeProcess static methods which rely on this in turn:
-	public static String WIN_KILL_CMD; 
+    // can't make this variable final and init in a static block, because it needs to use other SafeProcess static methods which rely on this in turn:
+    public static String WIN_KILL_CMD; 
 		
 	
@@ -118,9 +118,10 @@
     }
 
-	// In future, think of changing the method doRuntimeExec() over to using ProcessBuilder
-	// instead of Runtime.exec(). ProcessBuilder seems to have been introduced from Java 5.
-	// https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
-	// https://zeroturnaround.com/rebellabs/how-to-deal-with-subprocesses-in-java/
-	// which suggests using Apache Common Exec to launch processes and says what will be forthcoming in Java 9
+    // In future, think of changing the method doRuntimeExec() over to using ProcessBuilder
+    // instead of Runtime.exec(). ProcessBuilder seems to have been introduced from Java 5.
+    // https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
+    // https://zeroturnaround.com/rebellabs/how-to-deal-with-subprocesses-in-java/
+    // which suggests using Apache Common Exec to launch processes and says what will be forthcoming in Java 9
+    
     private Process doRuntimeExec() throws IOException {
 	Process prcs = null;
@@ -550,37 +551,35 @@
 public static long getProcessID(Process p)
 {
-	long pid = -1;
-	try
-	{
-		//for windows
-		if (p.getClass().getName().equals("java.lang.Win32Process") ||
-			   p.getClass().getName().equals("java.lang.ProcessImpl")) 
-		{
-			Field f = p.getClass().getDeclaredField("handle");
-			f.setAccessible(true);              
-			long handl = f.getLong(p);
-			Kernel32 kernel = Kernel32.INSTANCE;
-			WinNT.HANDLE hand = new WinNT.HANDLE();
-			hand.setPointer(Pointer.createConstant(handl));
-			pid = kernel.GetProcessId(hand);
-			f.setAccessible(false);
-		}
-		//for unix based operating systems
-		else if (p.getClass().getName().equals("java.lang.UNIXProcess")) 
-		{
-			Field f = p.getClass().getDeclaredField("pid");
-			f.setAccessible(true);
-			pid = f.getLong(p);
-			f.setAccessible(false);
-		}
-	}
-	catch(Exception ex)
-	{
-		log("SafeProcess.getProcessID(): Exception when attempting to get process ID for process " + ex.getMessage(), ex);	
-		pid = -1;
-	}
-	return pid;
+    long pid = -1;
+    try	{
+	//for windows
+	if (p.getClass().getName().equals("java.lang.Win32Process") ||
+	    p.getClass().getName().equals("java.lang.ProcessImpl")) 
+	    {
+		Field f = p.getClass().getDeclaredField("handle");
+		f.setAccessible(true);              
+		long handl = f.getLong(p);
+		Kernel32 kernel = Kernel32.INSTANCE;
+		WinNT.HANDLE hand = new WinNT.HANDLE();
+		hand.setPointer(Pointer.createConstant(handl));
+		pid = kernel.GetProcessId(hand);
+		f.setAccessible(false);
+	    }
+	//for unix based operating systems
+	else if (p.getClass().getName().equals("java.lang.UNIXProcess")) 
+	    {
+		Field f = p.getClass().getDeclaredField("pid");
+		f.setAccessible(true);
+		pid = f.getLong(p);
+		f.setAccessible(false);
+	    }
+
+    } catch(Exception ex) {
+	log("SafeProcess.getProcessID(): Exception when attempting to get process ID for process " + ex.getMessage(), ex);	
+	pid = -1;
+    }
+    return pid;
 }
-
+    
 
 // stackoverflow.com/questions/1835885/send-ctrl-c-to-process-open-by-java	
@@ -589,17 +588,17 @@
 // Searching for: "forcibly terminate external process launched by Java on Windows"	
 static void killWinProcessWithID(long processID) {
-	
-	String cmd = SafeProcess.getWinProcessKillCmd(processID);
-	if (cmd == null) return;
-	
-	try{		
-		log("\tAttempting to terminate Win subprocess with pid: " + processID);
-		SafeProcess proc = new SafeProcess(cmd);			
-		int exitValue = proc.runProcess(); // no IOstreams for Taskkill, but for "wmic process pid delete"
-			// there is output that needs flushing, so don't use runBasicProcess()
+    
+    String cmd = SafeProcess.getWinProcessKillCmd(processID);
+    if (cmd == null) return;
+    
+    try {		
+	log("\tAttempting to terminate Win subprocess with pid: " + processID);
+	SafeProcess proc = new SafeProcess(cmd);			
+	int exitValue = proc.runProcess(); // no IOstreams for Taskkill, but for "wmic process pid delete"
+	// there is output that needs flushing, so don't use runBasicProcess()
 			
-	} catch(Exception e) {
-		log("@@@ Exception attempting to stop perl " + e.getMessage(), e);		
-	}
+    } catch(Exception e) {
+	log("@@@ Exception attempting to stop perl " + e.getMessage(), e);		
+    }
 }
 
@@ -609,26 +608,26 @@
 // e.g. full-import.pl may be terminated with p.destroy(), but it launches import.pl which is left running until it naturally terminates.
 static void destroyProcess(Process p) {
-	// If it isn't windows, process.destroy() terminates any child processes too
-	if(!Utility.isWindows()) {
-		p.destroy();
-		return;
-	}	
-
-	if(!SafeProcess.isAvailable("wmic")) {
-		log("wmic, used to kill subprocesses, is not available. Unable to terminate subprocesses...");
-		log("Kill them manually from the TaskManager or they will proceed to run to termination");
-		
-		// At least we can get rid of the top level process we launched
-		p.destroy();
-		return;
-	}	
-	
-	// get the process id of the process we launched,
-	// so we can use it to find the pids of any subprocesses it launched in order to terminate those too.
-	
-	long processID = SafeProcess.getProcessID(p);		
-	log("Attempting to terminate sub processes of Windows process with pid " + processID);
-	terminateSubProcessesRecursively(processID, p);
-	
+    // If it isn't windows, process.destroy() terminates any child processes too
+    if(!Utility.isWindows()) {
+	p.destroy();
+	return;
+    }	
+    
+    if(!SafeProcess.isAvailable("wmic")) {
+	log("wmic, used to kill subprocesses, is not available. Unable to terminate subprocesses...");
+	log("Kill them manually from the TaskManager or they will proceed to run to termination");
+	
+	// At least we can get rid of the top level process we launched
+	p.destroy();
+	return;
+    }	
+    
+    // get the process id of the process we launched,
+    // so we can use it to find the pids of any subprocesses it launched in order to terminate those too.
+    
+    long processID = SafeProcess.getProcessID(p);		
+    log("Attempting to terminate sub processes of Windows process with pid " + processID);
+    terminateSubProcessesRecursively(processID, p);
+    
 }
 
@@ -642,88 +641,90 @@
 private static void terminateSubProcessesRecursively(long parent_pid, Process p) {
 	
-	// Use Windows wmic to find the pids of any sub processes launched by the process denoted by parent_pid	
-	SafeProcess proc = new SafeProcess("wmic process where (parentprocessid="+parent_pid+") get processid");
-	proc.setSplitStdOutputNewLines(true); // since this is windows, splits lines by \r\n
-	int exitValue = proc.runProcess(); // exitValue (%ERRORLEVEL%) is 0 either way.	
-	//log("@@@@ Return value from proc: " + exitValue);
-	
-	// need output from both stdout and stderr: stderr will say there are no pids, stdout will contain pids
-	String stdOutput = proc.getStdOutput();
-	String stdErrOutput = proc.getStdError();
-	
-	
-	// Now we know the pids of the immediate subprocesses, we can get rid of the parent process
-	if(p != null) { // we're the top level process, terminate java way
-		p.destroy();
-	} else { // terminate windows way		
-		SafeProcess.killWinProcessWithID(parent_pid); // get rid off current pid		
-	}
-	
-	// parse the output to get the sub processes' pids	
-	// Output looks like:
-	// ProcessId
-	// 6040
-	// 180
-	// 4948
-	// 1084
-	// 6384
-	// If no children, then STDERR output starts with the following, possibly succeeded by empty lines:
-	// No Instance(s) Available.
-	
-	// base step of the recursion
-	if(stdErrOutput.indexOf("No Instance(s) Available.") != -1) { 
-		//log("@@@@ Got output on stderr: " + stdErrOutput);
-		// No further child processes. And we already terminated the parent process, so we're done
-		return;
-	} else {
-		//log("@@@@ Got output on stdout:\n" + stdOutput);
-	
-		// http://stackoverflow.com/questions/691184/scanner-vs-stringtokenizer-vs-string-split	
-	
-		// find all childprocesses for that pid and terminate them too:
-		Stack<Long> subprocs = new Stack<Long>();
-		Scanner sc = new Scanner(stdOutput);
-		while (sc.hasNext()) {
-		  if(!sc.hasNextLong()) {
-			  sc.next(); // discard the current token since it's not a Long
-		  } else {
-			long child_pid = sc.nextLong();
-			subprocs.push(new Long(child_pid));			
-		  }
-		}
-		sc.close();		
-		
-		// recursion step if subprocs is not empty (but if it is empty, then it's another base step)
-		if(!subprocs.empty()) {
-			long child_pid = subprocs.pop().longValue();
-			terminateSubProcessesRecursively(child_pid, null);
-		}	
-	}
+    // Use Windows wmic to find the pids of any sub processes launched by the process denoted by parent_pid	
+    SafeProcess proc = new SafeProcess("wmic process where (parentprocessid="+parent_pid+") get processid");
+    proc.setSplitStdOutputNewLines(true); // since this is windows, splits lines by \r\n
+    int exitValue = proc.runProcess(); // exitValue (%ERRORLEVEL%) is 0 either way.	
+    //log("@@@@ Return value from proc: " + exitValue);
+    
+    // need output from both stdout and stderr: stderr will say there are no pids, stdout will contain pids
+    String stdOutput = proc.getStdOutput();
+    String stdErrOutput = proc.getStdError();
+    
+    
+    // Now we know the pids of the immediate subprocesses, we can get rid of the parent process
+    // We know the children remain running: since the whole problem on Windows is that these
+    // child processes remain running as orphans after the parent is forcibly terminated.
+    if(p != null) { // we're the top level process, terminate the java way
+	p.destroy();
+    } else { // terminate windows way		
+	SafeProcess.killWinProcessWithID(parent_pid); // get rid off current pid		
+    }
+    
+    // parse the output to get the sub processes' pids	
+    // Output looks like:
+    // ProcessId
+    // 6040
+    // 180
+    // 4948
+    // 1084
+    // 6384
+    // If no children, then STDERR output starts with the following, possibly succeeded by empty lines:
+    // No Instance(s) Available.
+    
+    // base step of the recursion
+    if(stdErrOutput.indexOf("No Instance(s) Available.") != -1) { 
+	//log("@@@@ Got output on stderr: " + stdErrOutput);
+	// No further child processes. And we already terminated the parent process, so we're done
+	return;
+    } else {
+	//log("@@@@ Got output on stdout:\n" + stdOutput);
+	
+	// http://stackoverflow.com/questions/691184/scanner-vs-stringtokenizer-vs-string-split	
+	
+	// find all childprocesses for that pid and terminate them too:
+	Stack<Long> subprocs = new Stack<Long>();
+	Scanner sc = new Scanner(stdOutput);
+	while (sc.hasNext()) {
+	    if(!sc.hasNextLong()) {
+		sc.next(); // discard the current token since it's not a Long
+	    } else {
+		long child_pid = sc.nextLong();
+		subprocs.push(new Long(child_pid));			
+	    }
+	}
+	sc.close();		
+	
+	// recursion step if subprocs is not empty (but if it is empty, then it's another base step)
+	if(!subprocs.empty()) {
+	    long child_pid = subprocs.pop().longValue();
+	    terminateSubProcessesRecursively(child_pid, null);
+	}	
+    }
 }
 
 // This method should only be called on a Windows OS
 private static String getWinProcessKillCmd(Long processID) {
-	// check if we first need to init WIN_KILL_CMD. We do this only once, but can't do it in a static codeblock
-	
-	if(WIN_KILL_CMD == null) {		
-		if(SafeProcess.isAvailable("wmic")) {
-			// https://isc.sans.edu/diary/Windows+Command-Line+Kung+Fu+with+WMIC/1229
-			WIN_KILL_CMD = "wmic process _PROCID_ delete"; // like "kill -9" on Windows
-		}
-		else if(SafeProcess.isAvailable("taskkill")) { // check if we have taskkill or else use the longstanding tskill
-		
-			WIN_KILL_CMD = "taskkill /f /t /PID _PROCID_"; // need to forcefully /f terminate the process				
-				//  /t "Terminates the specified process and any child processes which were started by it."
-				// But despite the /T flag, the above doesn't kill subprocesses.
-		}
-		else { //if(SafeProcess.isAvailable("tskill")) { can't check availability since "which tskill" doesn't ever succeed
-			WIN_KILL_CMD = "tskill _PROCID_"; // https://ss64.com/nt/tskill.html
-		}		
-	}
-	
-	if(WIN_KILL_CMD == null) { // can happen if none of the above cmds were available
-		return null;
-	}
-	return WIN_KILL_CMD.replace( "_PROCID_", Long.toString(processID) );
+    // check if we first need to init WIN_KILL_CMD. We do this only once, but can't do it in a static codeblock
+    
+    if(WIN_KILL_CMD == null) {		
+	if(SafeProcess.isAvailable("wmic")) {
+	    // https://isc.sans.edu/diary/Windows+Command-Line+Kung+Fu+with+WMIC/1229
+	    WIN_KILL_CMD = "wmic process _PROCID_ delete"; // like "kill -9" on Windows
+	}
+	else if(SafeProcess.isAvailable("taskkill")) { // check if we have taskkill or else use the longstanding tskill
+	    
+	    WIN_KILL_CMD = "taskkill /f /t /PID _PROCID_"; // need to forcefully /f terminate the process				
+	        //  /t "Terminates the specified process and any child processes which were started by it."
+	        // But despite the /T flag, the above doesn't kill subprocesses.
+	}
+	else { //if(SafeProcess.isAvailable("tskill")) { can't check availability since "which tskill" doesn't ever succeed
+	    WIN_KILL_CMD = "tskill _PROCID_"; // https://ss64.com/nt/tskill.html
+	}		
+    }
+    
+    if(WIN_KILL_CMD == null) { // can happen if none of the above cmds were available
+	return null;
+    }
+    return WIN_KILL_CMD.replace( "_PROCID_", Long.toString(processID) );
 }
 
@@ -735,18 +736,18 @@
 // On windows, "which tskill" fails but "which" succeeds on taskkill|wmic|browser names.
 public static boolean isAvailable(String program) {		
-	try {
-	    // On linux `which bla` does nothing, prompt is returned; on Windows, it prints "which: no bla in"
-	    // `which grep` returns a line of output with the path to grep. On windows too, the location of the program is printed
-	    SafeProcess prcs = new SafeProcess("which " + program);		
-	    prcs.runProcess();
-	    String output = prcs.getStdOutput();
-	    if(output.equals("")) {
-		return false;
-	    }
-	    //System.err.println("*** 'which " + program + "' returned: " + output);
-	    return true;
-	} catch (Exception exc) {
+    try {
+	// On linux `which bla` does nothing, prompt is returned; on Windows, it prints "which: no bla in"
+	// `which grep` returns a line of output with the path to grep. On windows too, the location of the program is printed
+	SafeProcess prcs = new SafeProcess("which " + program);		
+	prcs.runProcess();
+	String output = prcs.getStdOutput();
+	if(output.equals("")) {
 	    return false;
 	}
+	//System.err.println("*** 'which " + program + "' returned: " + output);
+	return true;
+    } catch (Exception exc) {
+	return false;
+    }
 }	
 	
