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