How to properly stop phantomjs execution

Question:

I initiated and close phantomjs in Python with the following

from selenium import webdriver    
driver = webdriver.PhantomJS()
driver.get(url)
html_doc = driver.page_source
driver.close()

yet after the script ends execution I still find an instance of phantomjs in my Mac Activity Monitor. And actually every time I run the script a new process phantomjs is created.

How should I close the driver?

Asked By: CptNemo

||

Answers:

The .close() method is not guaranteed to release all resources associated with a driver instance. Note that these resources include, but may not be limited to, the driver executable (PhantomJS, in this case). The .quit() method is designed to free all resources of a driver, including exiting the executable process.

Answered By: JimEvans

Please note that this will obviously cause trouble if you have several threads/processes starting PhantomJS on your machine.

I’ve seen several people struggle with the same issue, but for me, the simplest workaround/hack was to execute the following from the command line through Python AFTER you have invoked driver.close() or driver.quit():

pgrep phantomjs | xargs kill
Answered By: whirlwin

I was having a similar issue on Windows machine. I had no luck with either

driver.close()

or

driver.quit()

actually closing out of the PhantomJS window, but when I used both, the PhantomJS window finally closed and exited properly.

driver.close()
driver.quit()
Answered By: John H.

driver.quit() did not work for me on Windows 10, so I ended up adding the following line right after calling driver.close():

os.system('taskkill /f /im phantomjs.exe')

where

/f = force
/im = by image name

And since this is a Windows only solution, it may be wise to only execute if os.name == 'nt'

Answered By: FoxMulder900

What is the OS you are using? I think it corresponds to the case of the next, if you are using the POSIX OS.

I create pull request, but it rejected.
https://github.com/SeleniumHQ/selenium/pull/2244

But I think obviously the correct it. Therefore , I issued a issue.
https://github.com/SeleniumHQ/selenium/issues/2272

The root cause of this problem is that the end method of ghost driver mode phatmojs is incorrect. It is not not use the shutdown API of ghost driver mode phantomjs at the end.

In the case of phantomjs that you installed in npm on Linux or OSX,
A selenium call Popen for phantomjs, A phantomjs call spawn for lib/phantomjs.js. At this time, a selenium is parent, a phantomjs is child, and lib/phantomjs.js is grandchild.

You call quit() in parent(selenium), it send SIGTERM to child(phantomjs). and a child(phantomjs) send SIGTERM to grandchild(lib/phantomjs.js) in the child’s SIGTERM handler function.

A grandchild will be zombie when parent send SIGKILL to child before the child send SIGTERM to grandchild.

This pull request ttps://github.com/SeleniumHQ/selenium/pull/2244 be shutdown using ghost driver mode shutdown api.

 def send_remote_shutdown_command(self):
      super(Service, self).send_remote_shutdown_command()  ## ADD A NEW LINE HERE
      if self._cookie_temp_file:
          os.close(self._cookie_temp_file_handle)
          os.remove(self._cookie_temp_file)

Other solutions, sleep between “self.process.ternimate()” and “self.process.kill()”.
ttps://github.com/SeleniumHQ/selenium/blob/051c8b110a1aec35247cd45fa4db85c6e522cdcb/py/selenium/webdriver/common/service.py#L151-L153

        self.process.terminate()
        time.sleep(1)  ## ADD A NEW LINE HERE
        self.process.kill()
        self.process.wait()
Answered By: TakesxiSximada

As of July 2016, driver.close() and driver.quit() weren’t sufficient for me. That killed the node process but not the phantomjs child process it spawned.

Following the discussion on this GitHub issue, the single solution that worked for me was to run:

import signal

driver.service.process.send_signal(signal.SIGTERM) # kill the specific phantomjs child proc
driver.quit()                                      # quit the node proc
Answered By: leekaiinthesky

I also have a python script running on my mac using selenium to do some stuff using PhantomJS as the webdriver.

When my test is running, there are three processes to note are here:

$ ps -ef | grep [p]hantomjs
  501 28085 24925   0  9:03pm ttys002    0:00.34 python test.py
  501 28088 28085   0  9:03pm ttys002    0:00.14 node /usr/local/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
  501 28090 28088   0  9:03pm ttys002    0:00.71 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075

Note the second column which are the process numbers, and the third which are that processes parent.
My test script is the parent. There is a node process which has my test script as a parent, then there is another PhantomJS process whose parent is the node process. Don’t ask me why there’s two PhantomJS processes, I guess it is just how it’s designed to work?

Anyway, in my mac’s activity monitor, I can see this:

enter image description here

Note the PID number 28090.

After my test finishes running this, processes hangs around, just like you too. If I check for still running processes I can see:

$ ps -ef | grep [p]hantomjs
  501 28090     1   0  9:03pm ttys002    0:18.93 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075

So it appears to me that driver.quit() exits the node process, the one with PID number 28088, but it leaves its child orphaned. I don’t know if this is intentional. If it’s not intentional, then I think there isn’t a ‘proper’ way to exit this process in your code.

Therefore I would use your language’s equivalent of kill -9 28090, just after driver.quit()

Answered By: Sebastian