# ---------------------------------------------------------------------------
#
# Copyright (c) 2005, Greg Stein
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
# ---------------------------------------------------------------------------
#
# This software lives at:
#    http://gstein.googlecode.com/svn/trunk/python/daemonize.py
#

import os
import signal
import sys
import time
import multiprocessing  # requires Python 2.6


# possible return values from Daemon.daemonize()
DAEMON_RUNNING = 'The daemon is running'
DAEMON_NOT_RUNNING = 'The daemon is not running'
DAEMON_COMPLETE = 'The daemon has completed its operations'
DAEMON_STARTED = 'The daemon has been started'


class Daemon(object):

  def __init__(self, logfile, pidfile):
    self.logfile = logfile
    self.pidfile = pidfile

  def foreground(self):
    "Run in the foreground."
    ### we should probably create a pidfile. other systems may try to detect
    ### the pidfile to see if this "daemon" is running.
    self.setup()
    self.run()
    ### remove the pidfile

  def daemonize_exit(self):
    try:
      result = self.daemonize()
    except (ChildFailed, DaemonFailed), e:
      # duplicate the exit code
      sys.exit(e.code)
    except (ChildTerminatedAbnormally, ChildForkFailed,
            DaemonTerminatedAbnormally, DaemonForkFailed), e:
      sys.stderr.write('ERROR: %s\n' % e)
      sys.exit(1)
    except ChildResumedIncorrectly:
      sys.stderr.write('ERROR: continued after receiving unknown signal.\n')
      sys.exit(1)

    if result == DAEMON_STARTED or result == DAEMON_COMPLETE:
      sys.exit(0)
    elif result == DAEMON_NOT_RUNNING:
      sys.stderr.write('ERROR: the daemon exited with a success code '
                       'without signalling its startup.\n')
      sys.exit(1)

    # in original process. daemon is up and running. we're done.

  def daemonize(self):
    ### review error situations. map to backwards compat. ??
    ### be mindful of daemonize_exit().
    ### we should try and raise ChildFailed / ChildTerminatedAbnormally.
    ### ref: older revisions. OR: remove exceptions.

    child_is_ready = multiprocessing.Event()
    child_completed = multiprocessing.Event()

    p = multiprocessing.Process(target=self._first_child,
                                args=(child_is_ready, child_completed))
    p.start()

    # Wait for the child to finish setting things up (in case we need
    # to communicate with it). It will only exit when ready.
    ### use a timeout here! (parameterized, of course)
    p.join()

    ### need to propagate errors, to adjust the return codes
    if child_completed.is_set():
      ### what was the exit status?
      return DAEMON_COMPLETE
    if child_is_ready.is_set():
      return DAEMON_RUNNING

    ### how did we get here?! the immediate child should not exit without
    ### signalling ready/complete. some kind of error.
    return DAEMON_STARTED

  def _first_child(self, child_is_ready, child_completed):
    # we're in the child.

    ### NOTE: the original design was a bit bunk. Exceptions raised from
    ### this point are within the child processes. We need to signal the
    ### errors to the parent in other ways.

    # decouple from the parent process
    os.chdir('/')
    os.umask(0)
    os.setsid()

    # remember this pid so the second child can signal it.
    thispid = os.getpid()

    # if the daemon process exits before signalling readiness, then we
    # need to see the problem. trap SIGCHLD with a SignalCatcher.
    daemon_exit = SignalCatcher(signal.SIGCHLD)

    # perform the second fork
    try:
      pid = os.fork()
    except OSError, e:
      ### this won't make it to the parent process
      raise DaemonForkFailed(e.errno, e.strerror)

    if pid > 0:
      # in the parent.


      # Wait for the child to be ready for operation.
      while True:
        # The readiness event will invariably be signalled early/first.
        # If it *doesn't* get signalled because the child has prematurely
        # exited, then we will pause 10ms before noticing the exit. The
        # pause is acceptable since that is aberrant/unexpected behavior.
        ### is there a way to break this wait() on a signal such as SIGCHLD?
        ### parameterize this wait, in case the app knows children may
        ### fail quickly?
        if child_is_ready.wait(timeout=0.010):
          # The child signalled readiness. Yay!
          break
        if daemon_exit.signalled:
          # Whoops. The child exited without signalling :-(
          break
        # Python 2.6 compat: .wait() may exit when set, but return None
        if child_is_ready.is_set():
          break
        # A simple timeout. The child is taking a while to prepare. Go
        # back and wait for readiness.

      if daemon_exit.signalled:
        # Tell the parent that the child has exited.
        ### we need to communicate the exit status, if possible.
        child_completed.set()

        # reap the daemon process, getting its exit code. bubble it up.
        cpid, status = os.waitpid(pid, 0)
        assert pid == cpid
        if os.WIFEXITED(status):
          code = os.WEXITSTATUS(status)
          if code:
            ### this won't make it to the parent process
            raise DaemonFailed(code)
          ### this return value is ignored
          return DAEMON_NOT_RUNNING

        # the daemon did not exit cleanly.
        ### this won't make it to the parent process
        raise DaemonTerminatedAbnormally(status)

      # child_is_ready got asserted. the daemon is up and running, so
      # save the pid and return success.
      if self.pidfile:
        # Be wary of symlink attacks
        try:
          os.remove(self.pidfile)
        except OSError:
          pass
        fd = os.open(self.pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0444)
        os.write(fd, '%d\n' % pid)
        os.close(fd)

      ### this return value is ignored
      return DAEMON_STARTED

      ### old code. what to do with this? throw ChildResumedIncorrectly
      ### or just toss this and the exception.
      # some other signal popped us out of the pause. the daemon might not
      # be running.
      ### this won't make it to the parent process
      raise ChildResumedIncorrectly()

    # we're a daemon now. get rid of the final remnants of the parent:
    # restore the signal handlers and switch std* to the proper files.
    signal.signal(signal.SIGUSR1, signal.SIG_DFL)
    signal.signal(signal.SIGCHLD, signal.SIG_DFL)
    sys.stdout.flush()
    sys.stderr.flush()
    si = open('/dev/null', 'r')
    so = open(self.logfile, 'a+')
    se = open(self.logfile, 'a+', 0)  # unbuffered
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())
    # note: we could not inline the open() calls. after the fileno() completed,
    # the file would be closed, making the fileno invalid. gotta hold them
    # open until now:
    si.close()
    so.close()
    se.close()

    ### TEST: don't release the parent immediately. the whole parent stack
    ###       should pause along with this sleep.
    #time.sleep(10)

    # everything is set up. call the initialization function.
    self.setup()

    ### TEST: exit before signalling.
    #sys.exit(0)
    #sys.exit(1)

    # the child is now ready for parent/anyone to communicate with it.
    child_is_ready.set()

    # start the daemon now.
    self.run()

    # The daemon is shutting down, so toss the pidfile.
    if self.pidfile:
      try:
        os.remove(self.pidfile)
      except OSError:
        pass

    ### this return value is ignored
    return DAEMON_COMPLETE

  def setup(self):
    raise NotImplementedError

  def run(self):
    raise NotImplementedError


class _Detacher(Daemon):
  def __init__(self, target, logfile='/dev/null', pidfile=None,
               args=(), kwargs={}):
    Daemon.__init__(self, logfile, pidfile)
    self.target = target
    self.args = args
    self.kwargs = kwargs

  def setup(self):
    pass

  def run(self):
    self.target(*self.args, **self.kwargs)


def run_detached(target, *args, **kwargs):
  """Simple function to run TARGET as a detached daemon.

  The additional arguments/keywords will be passed along. This function
  does not return -- sys.exit() will be called as appropriate.

  (capture SystemExit if logging/reporting is necessary)
  ### if needed, a variant of this func could be written to not exit
  """
  d = _Detacher(target, args=args, kwargs=kwargs)
  d.daemonize_exit()


class SignalCatcher(object):
  def __init__(self, signum):
    self.signalled = False
    signal.signal(signum, self.sig_handler)

  def sig_handler(self, signum, frame):
    self.signalled = True


class ChildTerminatedAbnormally(Exception):
  "The child process terminated abnormally."
  def __init__(self, status):
    Exception.__init__(self, status)
    self.status = status
  def __str__(self):
    return 'child terminated abnormally (0x%04x)' % self.status

class ChildFailed(Exception):
  "The child process exited with a failure code."
  def __init__(self, code):
    Exception.__init__(self, code)
    self.code = code
  def __str__(self):
    return 'child failed with exit code %d' % self.code

class ChildForkFailed(Exception):
  "The child process could not be forked."
  def __init__(self, errno, strerror):
    Exception.__init__(self, errno, strerror)
    self.errno = errno
    self.strerror = strerror
  def __str__(self):
    return 'child fork failed with error %d (%s)' % self.args

class ChildResumedIncorrectly(Exception):
  "The child resumed its operation incorrectly."

class DaemonTerminatedAbnormally(Exception):
  "The daemon process terminated abnormally."
  def __init__(self, status):
    Exception.__init__(self, status)
    self.status = status
  def __str__(self):
    return 'daemon terminated abnormally (0x%04x)' % self.status

class DaemonFailed(Exception):
  "The daemon process exited with a failure code."
  def __init__(self, code):
    Exception.__init__(self, code)
    self.code = code
  def __str__(self):
    return 'daemon failed with exit code %d' % self.code

class DaemonForkFailed(Exception):
  "The daemon process could not be forked."
  def __init__(self, errno, strerror):
    Exception.__init__(self, errno, strerror)
    self.errno = errno
    self.strerror = strerror
  def __str__(self):
    return 'daemon fork failed with error %d (%s)' % self.args
