import os
import signal
-from .common import ST_ACTIVE, ST_TRANSITION, OnoffDevice
-from .gobject import spawn_child, ScheduledFunction
+from .common import OnoffDevice, OnoffState
+from .gobject import spawn_child
logger = logging.getLogger("onoff.process")
@ivar killed: indicates whether the termination signal has been sent
to the spawned process.
"""
- def __init__(self, command, start_wait=0, termsig=signal.SIGTERM):
+ def __init__(self, command, termsig=signal.SIGTERM):
"""
@type command: [str]
@param command: an argument vector to be executed. The first element
is used as executable and looked up in $PATH.
- @param start_wait: duration of the transition period from inactive to
- active in seconds.
@param termsig: termination signal to be sent to the process to
deactivate it. The process must exit in response to this
signal.
"""
OnoffDevice.__init__(self)
self.command = command
- self.start_wait = start_wait
self.termsig = termsig
- self.desired_state = 0 # bit mask of just ST_ACTIVE
+ self.desired_state = OnoffState.inactive
self.pid = None
- self.starting = None # timeout event during start
self.killed = False
@property
def state(self):
- if self.starting or self.killed:
- return self.desired_state | ST_TRANSITION
+ if self.killed:
+ return self.desired_state | OnoffState.transition
return self.desired_state
def start_process(self):
assert self.pid is None
- assert self.starting is None
logger.info("starting command %s", " ".join(self.command))
self.pid = spawn_child(self.command, self.process_died)
logger.debug("started as pid %d", self.pid)
- self.starting = ScheduledFunction(self.start_wait, self.process_started)
+ assert self.desired_state == OnoffState.active
+ logger.debug("process started")
self.changestate(self.state)
- def cancel_start_wait(self):
- if self.starting is None:
- return
- logger.debug("cancelling start notification")
- self.starting.cancel()
- self.starting = None
-
def process_died(self, pid, condition):
assert self.pid == pid
self.pid = None
self.killed = False
logger.info("process %d died", pid)
- self.cancel_start_wait()
- if self.desired_state == ST_ACTIVE:
+ if self.desired_state == OnoffState.active:
self.start_process()
else:
self.changestate(self.state)
- def process_started(self):
- assert self.desired_state == ST_ACTIVE
- assert self.starting is not None
- self.starting = None
- logger.debug("process started")
- self.changestate(self.state)
-
- def stop_process(self):
- assert self.pid is not None
- self.cancel_start_wait()
- logger.info("killing process %d", self.pid)
- os.kill(self.pid, self.termsig)
- self.killed = True
- self.changestate(self.state)
-
def activate(self):
- if self.desired_state != ST_ACTIVE:
- self.desired_state = ST_ACTIVE
+ if self.desired_state != OnoffState.active:
+ self.desired_state = OnoffState.active
if self.pid is None:
self.start_process()
else:
logger.debug("already activated. nothing to do")
def deactivate(self):
- if self.desired_state != 0:
- self.desired_state = 0
+ if self.desired_state != OnoffState.inactive:
+ self.desired_state = OnoffState.inactive
if self.pid is not None and not self.killed:
- self.stop_process()
+ logger.info("killing process %d", self.pid)
+ os.kill(self.pid, self.termsig)
+ self.killed = True
+ self.changestate(self.state)
else:
logger.debug("already deactivated. nothing to do.")