1 #!/usr/bin/python 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 import os 7 import signal 8 import subprocess 9 import time 10 11 class BrowserProcessBase(object): 12 13 def __init__(self, handle): 14 self.handle = handle 15 print 'PID', self.handle.pid 16 17 def GetReturnCode(self): 18 return self.handle.returncode 19 20 def IsRunning(self): 21 return self.handle.poll() is None 22 23 def Wait(self, wait_steps, sleep_time): 24 self.term() 25 i = 0 26 # subprocess.wait() doesn't have a timeout, unfortunately. 27 while self.IsRunning() and i < wait_steps: 28 time.sleep(sleep_time) 29 i += 1 30 31 def Kill(self): 32 if self.IsRunning(): 33 print 'KILLING the browser' 34 try: 35 self.kill() 36 # If it doesn't die, we hang. Oh well. 37 self.handle.wait() 38 except Exception: 39 # If it is already dead, then it's ok. 40 # This may happen if the browser dies after the first poll, but 41 # before the kill. 42 if self.IsRunning(): 43 raise 44 45 class BrowserProcess(BrowserProcessBase): 46 47 def term(self): 48 self.handle.terminate() 49 50 def kill(self): 51 self.handle.kill() 52 53 54 class BrowserProcessPosix(BrowserProcessBase): 55 """ This variant of BrowserProcess uses process groups to manage browser 56 life time. """ 57 58 def term(self): 59 os.killpg(self.handle.pid, signal.SIGTERM) 60 61 def kill(self): 62 os.killpg(self.handle.pid, signal.SIGKILL) 63 64 65 def RunCommandWithSubprocess(cmd, env=None): 66 handle = subprocess.Popen(cmd, env=env) 67 return BrowserProcess(handle) 68 69 70 def RunCommandInProcessGroup(cmd, env=None): 71 def SetPGrp(): 72 os.setpgrp() 73 print 'I\'M THE SESSION LEADER!' 74 handle = subprocess.Popen(cmd, env=env, preexec_fn=SetPGrp) 75 return BrowserProcessPosix(handle) 76 77