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 6from __future__ import print_function 7 8import os 9import signal 10import subprocess 11import time 12 13class BrowserProcessBase(object): 14 15 def __init__(self, handle): 16 self.handle = handle 17 print('PID', self.handle.pid) 18 19 def GetReturnCode(self): 20 return self.handle.returncode 21 22 def IsRunning(self): 23 return self.handle.poll() is None 24 25 def Wait(self, wait_steps, sleep_time): 26 try: 27 self.term() 28 except Exception: 29 # Terminating the handle can raise an exception. There is likely no point 30 # in waiting if the termination didn't succeed. 31 return 32 33 i = 0 34 # subprocess.wait() doesn't have a timeout, unfortunately. 35 while self.IsRunning() and i < wait_steps: 36 time.sleep(sleep_time) 37 i += 1 38 39 def Kill(self): 40 if self.IsRunning(): 41 print('KILLING the browser') 42 try: 43 self.kill() 44 # If it doesn't die, we hang. Oh well. 45 self.handle.wait() 46 except Exception: 47 # If it is already dead, then it's ok. 48 # This may happen if the browser dies after the first poll, but 49 # before the kill. 50 if self.IsRunning(): 51 raise 52 53class BrowserProcess(BrowserProcessBase): 54 55 def term(self): 56 self.handle.terminate() 57 58 def kill(self): 59 self.handle.kill() 60 61 62class BrowserProcessPosix(BrowserProcessBase): 63 """ This variant of BrowserProcess uses process groups to manage browser 64 life time. """ 65 66 def term(self): 67 os.killpg(self.handle.pid, signal.SIGTERM) 68 69 def kill(self): 70 os.killpg(self.handle.pid, signal.SIGKILL) 71 72 73def RunCommandWithSubprocess(cmd, env=None): 74 handle = subprocess.Popen(cmd, env=env) 75 return BrowserProcess(handle) 76 77 78def RunCommandInProcessGroup(cmd, env=None): 79 def SetPGrp(): 80 os.setpgrp() 81 print('I\'M THE SESSION LEADER!') 82 83 handle = subprocess.Popen(cmd, env=env, preexec_fn=SetPGrp) 84 return BrowserProcessPosix(handle) 85