import sys
import os
import signal
import subprocess
from collections import defaultdict
from inotify_simple import INotify, flags

def _wait_files_creation(file_list):
  # Establish a list of directory and subfiles.
  # and test existence before watching, so that we don't miss an event.
  directories = defaultdict(dict)
  for f in file_list:
    dirname, filename = os.path.split(f)
    directories[dirname][filename] = os.path.lexists(f)

  def all_files_exists():
    return all(all(files.itervalues()) for files in directories.itervalues())

  with INotify() as inotify:
    watchdescriptors = {inotify.add_watch(dirname,
        flags.CREATE | flags.DELETE | flags.MOVED_TO | flags.MOVED_FROM
        ): dirname
      for dirname in directories}

    while not all_files_exists():
      for event in inotify.read():
        directory = directories[watchdescriptors[event.wd]]
        if event.name in directory:
          directory[event.name] = event.mask & (flags.CREATE | flags.MOVED_TO)

def generic_exec(args, extra_environ=None, wait_list=None):
  args += sys.argv[1:]

  if wait_list:
    _wait_files_creation(wait_list)

  if extra_environ:
    env = os.environ.copy()
    env.update(extra_environ)
    os.execve(args[0], args, env)
  else:
    os.execv(args[0], args)

child_pg = None

def sig_handler(sig, frame):
  print 'Received signal %r, killing children and exiting' % sig
  if child_pg is not None:
    os.killpg(child_pg, signal.SIGHUP)
    os.killpg(child_pg, signal.SIGTERM)
  sys.exit()

def execute_with_signal_translation(args):
  """Run process as children and translate from SIGTERM to another signal"""
  global child_pg
  signal.signal(signal.SIGINT, sig_handler)
  signal.signal(signal.SIGQUIT, sig_handler)
  signal.signal(signal.SIGTERM, sig_handler)
  child = subprocess.Popen(args, close_fds=True, preexec_fn=os.setsid)
  child_pg = child.pid
  try:
    print 'Process %r started' % args
    signal.pause()
  finally:
    os.killpg(child_pg, signal.SIGHUP)
    os.killpg(child_pg, signal.SIGTERM)
