Revision 9b739173 lib/daemon.py

b/lib/daemon.py
44 44
    self._signal_wait = []
45 45
    self._poller = select.poll()
46 46

  
47
  def Run(self, handle_sigchld=True, handle_sigterm=True, stop_on_empty=False):
47
  @utils.SignalHandled([signal.SIGCHLD])
48
  @utils.SignalHandled([signal.SIGTERM])
49
  def Run(self, stop_on_empty=False, signal_handlers=None):
48 50
    """Runs the mainloop.
49 51

  
50
    @type handle_sigchld: bool
51
    @param handle_sigchld: Whether to install handler for SIGCHLD
52
    @type handle_sigterm: bool
53
    @param handle_sigterm: Whether to install handler for SIGTERM
54 52
    @type stop_on_empty: bool
55 53
    @param stop_on_empty: Whether to stop mainloop once all I/O waiters
56 54
                          unregistered
55
    @type signal_handlers: dict
56
    @param signal_handlers: signal->L{utils.SignalHandler} passed by decorator
57 57

  
58 58
    """
59
    # Setup signal handlers
60
    if handle_sigchld:
61
      sigchld_handler = utils.SignalHandler([signal.SIGCHLD])
62
    else:
63
      sigchld_handler = None
64
    try:
65
      if handle_sigterm:
66
        sigterm_handler = utils.SignalHandler([signal.SIGTERM])
67
      else:
68
        sigterm_handler = None
69

  
59
    assert isinstance(signal_handlers, dict) and \
60
           len(signal_handlers) > 0, \
61
           "Broken SignalHandled decorator"
62
    running = True
63
    # Start actual main loop
64
    while running:
65
      # Stop if nothing is listening anymore
66
      if stop_on_empty and not (self._io_wait):
67
        break
68

  
69
      # Wait for I/O events
70 70
      try:
71
        running = True
72

  
73
        # Start actual main loop
74
        while running:
75
          # Stop if nothing is listening anymore
76
          if stop_on_empty and not (self._io_wait):
77
            break
78

  
79
          # Wait for I/O events
80
          try:
81
            io_events = self._poller.poll(None)
82
          except select.error, err:
83
            # EINTR can happen when signals are sent
84
            if err.args and err.args[0] in (errno.EINTR,):
85
              io_events = None
86
            else:
87
              raise
88

  
89
          if io_events:
90
            # Check for I/O events
91
            for (evfd, evcond) in io_events:
92
              owner = self._io_wait.get(evfd, None)
93
              if owner:
94
                owner.OnIO(evfd, evcond)
95

  
96
          # Check whether signal was raised
97
          if sigchld_handler and sigchld_handler.called:
98
            self._CallSignalWaiters(signal.SIGCHLD)
99
            sigchld_handler.Clear()
100

  
101
          if sigterm_handler and sigterm_handler.called:
102
            self._CallSignalWaiters(signal.SIGTERM)
103
            running = False
104
            sigterm_handler.Clear()
105
      finally:
106
        # Restore signal handlers
107
        if sigterm_handler:
108
          sigterm_handler.Reset()
109
    finally:
110
      if sigchld_handler:
111
        sigchld_handler.Reset()
71
        io_events = self._poller.poll(None)
72
      except select.error, err:
73
        # EINTR can happen when signals are sent
74
        if err.args and err.args[0] in (errno.EINTR,):
75
          io_events = None
76
        else:
77
          raise
78

  
79
      if io_events:
80
        # Check for I/O events
81
        for (evfd, evcond) in io_events:
82
          owner = self._io_wait.get(evfd, None)
83
          if owner:
84
            owner.OnIO(evfd, evcond)
85

  
86
      # Check whether a signal was raised
87
      for sig in signal_handlers:
88
        handler = signal_handlers[sig]
89
        if handler.called:
90
          self._CallSignalWaiters(sig)
91
          running = (sig != signal.SIGTERM)
92
          handler.Clear()
112 93

  
113 94
  def _CallSignalWaiters(self, signum):
114 95
    """Calls all signal waiters for a certain signal.

Also available in: Unified diff