Ruby headless watir-webdriver Xvfb zombies

918 views Asked by At

I have two apps running on a single server that perform headless browsing tasks. Each time one browses, the Xvfb process is not dying and instead becomes a zombie. I can confirm this with the following script.

require 'headless'
require 'watir-webdriver'
require 'yaml'

zombies_at_start = `ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'`.split("\n").count

5.times do
  begin
    d = YAML.load_file("/path/to/config/headless.yml")['build_number'] #=> "98"
    h = Headless.new(:display => d) 
    h.start
    b = Watir::Browser.new :firefox
    b.goto 'http://google.com'
    sleep(0.5)
  ensure
    b.close
    h.destroy
  end
  sleep(0.5)
end

zombies_at_end = `ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'`.split("\n").count

puts "Created #{zombies_at_end - zombies_at_start} more zombies." 
#=> Created 5 more zombies.

Why? How can I fix this?


Version info:

  • xorg-x11-server-Xvfb-1.15.0-26.el6.centos.i686
  • CentOS release 6.5 (Final)
  • ruby-2.0.0-p353
  • rvm 1.25.25
  • selenium-webdriver (2.45.0, 2.44.0)
  • watir-webdriver (0.7.0)
  • headless (2.1.0)
1

There are 1 answers

0
Sam On BEST ANSWER

UPDATE: A pull request submitted to Headless to wait by default was accepted. Woo!


The gem headless changed the way it starts, stops (kills) and verifies the Xvfb process. Though I'm not entirely sure why, but on CentOS 6 this causes the process to zombify. Since the .destroy wasn't causing issues previously, it must be related to the way headless starts the Xvfb process (which was re-written simultaneously).

However, the gem simultaneously introduced .destroy_sync, which waits for the process to die, and does not create zombies.

require 'headless'
require 'watir-webdriver'
require 'yaml'

zombies_at_start = `ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'`.split("\n").count

5.times do
  begin
    d = YAML.load_file("/path/to/config/headless.yml")['build_number'] #=> "98"
    h = Headless.new(:display => d) 
    h.start
    b = Watir::Browser.new :firefox
    b.goto 'http://google.com'
    sleep(0.5)
  ensure
    b.close
    # h.destroy
    h.destroy_sync
  end
  sleep(0.5)
end

zombies_at_end = `ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'`.split("\n").count

puts "Created #{zombies_at_end - zombies_at_start} more zombies." 
#=> Created 0 more zombies.