5

After I run the phatomjs/java integration tests on the build server , the phantomjs processes still keep running in the background and have to be killed manually.

Is there a way to do this in the java code? I am already using driver.quit() in the test cleanup part. Is there anything else also to be included?

rsutormin
  • 1,629
  • 2
  • 17
  • 21
WorryNerd
  • 55
  • 1
  • 5
  • @WorryNerdWhat is the version of your phantomjs? – erhun Feb 11 '15 at 22:48
  • Similar question asked for phyton http://stackoverflow.com/questions/25110624/how-to-properly-stop-phantomjs-execution There is a work around here for linux system for manual process pgrep phantomjs | xargs kill – erhun Feb 11 '15 at 22:55
  • Thanks @erhun for redirecting to the question. that is the problem that I am facing right now but I can't kill the processes manually everytime. I am using driver.quit() in my code but still the processes are left in the server once the build has completed. Is there any thread that talks about adding a step in teamcity for killing the processes? – WorryNerd Feb 12 '15 at 17:42
  • I also have this problem with the `Wallaby` feature testing library for Phoenix / Elixir – Todd Jul 10 '18 at 21:09

2 Answers2

13

The simplest way (not necessarily the formal way) to deal with this issue is to shoot a kill command from bash script that terminates all phantomjs processes:

ps -ef | grep phantomjs | awk '{print $2}' | xargs sudo kill -9

The above script run in terminal will kill all background phantomjs whether you have started them using java or python or ruby... A quick workaround till the actual bug gets solved, imo.

Abhimanu Kumar
  • 1,751
  • 18
  • 20
  • 4
    this entire shell pipeline can be replaced by `killall -s SIGKILL phantomjs` or even `killall phantomjs` (if a SIGTERM suffices) – Corey Goldberg May 24 '17 at 19:30
  • 2
    @CoreyGoldberg `killall phantomjs` and `sudo killall phantomjs` had no effect on the many thousands of phantomjs processes that were running on my system. – Todd Jul 10 '18 at 21:10
0

this is a famous problem, which exist since December 2012 - UnreachableBrowserException

So, I made some workaround - was created class, which extends PhantomJSDriver with overridden method "execute":

@Override
protected Response execute(String driverCommand, Map<String, ?> parameters) {
    int retryAttempt = 0;

    while (true) {
        try {
            return super.execute(driverCommand, parameters);
        } catch (WebDriverException e) {
            retryAttempt++;
            if (retryAttempt > retryCount) {
                throw e;
            }
        }
    }
}

This is was helpful, but not always - sometimes phantomjs process did not stop working. So, I found a way to kill his process by PID (process id)

@Override
protected Response execute(String driverCommand, Map<String, ?> parameters) {
    int retryAttempt = 0;

    while (true) {
        try {
            return super.execute(driverCommand, parameters);
        } catch (WebDriverException e) {
            retryAttempt++;
            if (retryAttempt > retryCount) {
                if(driverCommand.equalsIgnoreCase("quit")) {
                    int port = GetDriverPort();
                    try {
                        int processID = GetPIDByServerPort(port);
                        boolean processExist = processID != -1;
                        if(processExist) {
                            log.info("Killing phantomJS, of process id:" + processID + " that listen to port:" + port);
                            KillPhantomProcess(processID);
                        }
                        return null;
                    } catch (IOException | InterruptedException ignore) {
                        throw e;
                    }
                }

                throw e;
            }
        }
    }
}

private int GetDriverPort(){
    return  ((HttpCommandExecutor)(this).getCommandExecutor()).getAddressOfRemoteServer().getPort();
}

private int GetPIDByServerPort(int port) throws InterruptedException, IOException {
    int pid = -1;
    ProcessBuilder p = new ProcessBuilder("cmd.exe", "/C", "netstat -no | findstr :" + String.valueOf(port));
    p.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);

    Process netstat = p.start();
    netstat.waitFor();
    InputStream inputStream = netstat.getInputStream();

    int bytesRead;
    byte[] bytes = new byte[1024];
    String result = "";
    while ((bytesRead = inputStream.read(bytes)) > -1) {
        result = result + new String(bytes, 0, bytesRead);
    }

    String[] lines = result.split("\\n+");
    for (String line : lines) {
        if(!(line.toUpperCase().contains("ESTABLISHED") && line.contains("127.0.0.1:" + port))) continue;

        String[] str = line.trim().split("\\s+");
        if(str[1].contains(String.valueOf(port))) pid = Integer.parseInt(str[4]);
    }

    return pid;
}

private void KillPhantomProcess(int pid) throws IOException  {
    try {
        Runtime.getRuntime().exec(TASKKILL_COMMAND + pid);
    } catch (IOException e) {
        log.error("Failed to kill phantomJs process. PID: " + pid, e);
        throw e;
    }

    if(pid > 0) log.info("phantomJs process " + pid + " was interrupted");
}

I hope this will helpfull