0

If I run the following command, there is a time-window where I can send SIGINT such that an instance of Firefox both opens and self.firefox is left undefined.

try:
    self.firefox = webdriver.Firefox(executable_path=os.getcwd()+"\\bin\\geckodriver.exe")  
except:
    pdb.set_trace()
    if hasattr(self, 'firefox'):
        self.firefox.quit()
    raise

Presumably this happens because the interrupt is occurring between points where selenium launches the browser and where it returns the reference.

While minor, when running headless tests, interrupts at the wrong time can leave FF instances open without reference. Is there a way to identify & manage Firefox instances that have been started by Selenium without killing any normal Firefox instances being run by a user on the machine?

Lovethenakedgun
  • 731
  • 6
  • 22

2 Answers2

0

To be precise, someone already answered how to stop geckodriver instance: [https://stackoverflow.com/a/48003289/6892765][1]

Now coming back to how to use it when the interrupts happen. As you are running tests you must be using a test engine such as pytest or likewise, which have a capability to handle such interrupts.

Specifically for pytest engine: Implement a pytest_exception_interact in a conftest.py file, which is called when an exception was raised which can potentially be interactively handled.

def pytest_exception_interact(node, call, report):
    # Your code to perform geckodriver instance killing
anurag0510
  • 763
  • 1
  • 8
  • 17
  • With regards to the answer you linked, I'm not sure what OS/Firefox/Geckodriver versions @DebanjanB was using, but that does not work for my setup. There are no tasks named "geckodriver.exe" in the tasklist, they all show up as "Firefox.exe", as do any normal Firefox instances. Given this, I don't want to just terminate all "Firefox" instances on the machine. Also the tests are manual, no testing engine or framework is in place atm. – Lovethenakedgun Jan 07 '19 at 06:27
0

I experimented with a couple things and ended up coming up with a solution based on the one linked through by learner8269. As noted in a comment on his post, on my system, Windows 10 / Current Geckodriver instances are not able to be distinguished from normal Firefox processes. As a result, I ended up wrapping the object creation with a try catch statement & the following code:

from subprocess import check_output
from selenium import webdriver
import re

tasklist = check_output(["tasklist", "/fi", "imagename eq firefox.exe"], shell=True).decode()
currentFFIDs = re.findall(r"firefox.exe\s+(\d+)", tasklist)
try:
    firefox = webdriver.Firefox()
except:
    tasklist = check_output(["tasklist", "/fi", "imagename eq firefox.exe"], shell=True).decode()
    firefoxIds = set(re.findall(r"firefox.exe\s+(\d+)", tasklist)).difference(currentFFIDs)
    taskkill = 'taskkill /f '+''.join(["/pid "+f+" " for f in firefoxIds]).strip()
    check_output(taskkill.split(), shell=True)
    print("\nFirefox was force closed\n", flush=True)

What this does is:

  • Get the current process IDs for running Firefox instances
  • This is done via subprocess calling the tasklist command in cmd and using a regular expression to extract the process ID column
  • Try and start the webdriver instance; if it succeeds, then good, otherwise run tasklist & get a new set of process IDs
    • This will now potentially include IDs started by Selenium
  • Convert the new IDs to a set & remove all the original IDs from it
  • Call "taskkill" and provide any new Firefox IDs created after the first tasklist process; this will then terminate any headless Firefox instances.
Lovethenakedgun
  • 731
  • 6
  • 22