Revision 09352fa4 test/ganeti.utils_unittest.py

b/test/ganeti.utils_unittest.py
32 32
import socket
33 33
import shutil
34 34
import re
35
import select
35 36

  
36 37
import ganeti
37 38
import testutils
......
45 46
from ganeti.errors import LockError, UnitParseError, GenericError, \
46 47
     ProgrammerError
47 48

  
48
def _ChildHandler(signal, stack):
49
  global _ChildFlag
50
  _ChildFlag = True
51

  
52 49

  
53 50
class TestIsProcessAlive(unittest.TestCase):
54 51
  """Testing case for IsProcessAlive"""
55 52

  
56
  def setUp(self):
57
    global _ChildFlag
58
    # create a (most probably) non-existing process-id
59
    self.pid_non_existing = os.fork()
60
    if self.pid_non_existing == 0:
61
      os._exit(0)
62
    elif self.pid_non_existing > 0:
63
      os.waitpid(self.pid_non_existing, 0)
64
    else:
65
      raise SystemError("can't fork")
66
    _ChildFlag = False
67
    # Use _ChildHandler for SIGCHLD
68
    self.chldOrig = signal.signal(signal.SIGCHLD, _ChildHandler)
53
  def _CreateZombie(self):
69 54
    # create a zombie
70
    self.pid_zombie = os.fork()
71
    if self.pid_zombie == 0:
55
    r_fd, w_fd = os.pipe()
56
    pid_zombie = os.fork()
57
    if pid_zombie == 0:
58
      # explicit close of read, write end will be closed only due to exit
59
      os.close(r_fd)
72 60
      os._exit(0)
73
    elif self.pid_zombie < 0:
61
    elif pid_zombie < 0:
74 62
      raise SystemError("can't fork")
75

  
76
  def tearDown(self):
77
    signal.signal(signal.SIGCHLD, self.chldOrig)
63
    # parent: we close our end of the w_fd, so reads will error as
64
    # soon as the OS cleans the child's filedescriptors on its exit
65
    os.close(w_fd)
66
    # wait for 60 seconds at max for the exit (pathological case, just
67
    # so that the test doesn't hang indefinitely)
68
    r_set, w_set, e_set = select.select([r_fd], [], [], 60)
69
    if not r_set and not e_set:
70
      self.fail("Timeout exceeded in zombie creation")
71
    return pid_zombie
78 72

  
79 73
  def testExists(self):
80 74
    mypid = os.getpid()
......
82 76
                 "can't find myself running")
83 77

  
84 78
  def testZombie(self):
85
    global _ChildFlag
86
    timeout = 10
87

  
88
    while not _ChildFlag:
89
      if timeout >= 0:
90
        time.sleep(0.2)
91
        timeout -= 0.2
92
      else:
93
        self.fail("timed out waiting for child's signal")
94
        break # not executed...
95

  
96
    self.assert_(not IsProcessAlive(self.pid_zombie),
97
                 "zombie not detected as zombie")
79
    pid_zombie = self._CreateZombie()
80
    is_zombie = not IsProcessAlive(pid_zombie)
81
    self.assert_(is_zombie, "zombie not detected as zombie")
82
    os.waitpid(pid_zombie, os.WNOHANG)
98 83

  
99 84
  def testNotExisting(self):
100
    self.assert_(not IsProcessAlive(self.pid_non_existing),
101
                 "noexisting process detected")
85
    pid_non_existing = os.fork()
86
    if pid_non_existing == 0:
87
      os._exit(0)
88
    elif pid_non_existing < 0:
89
      raise SystemError("can't fork")
90
    os.waitpid(pid_non_existing, 0)
91
    self.assert_(not IsProcessAlive(pid_non_existing),
92
                 "nonexisting process detected")
102 93

  
103 94

  
104 95
class TestPidFileFunctions(unittest.TestCase):

Also available in: Unified diff