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