#!/usr/bin/env python # # dispatcher.py - Subprocess running as root to call larch scripts # # (c) Copyright 2010 Michael Towers (larch42 at googlemail dot com) # # This file is part of the larch project. # # larch is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # larch is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with larch; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #---------------------------------------------------------------------------- #2010.07.19 import os, sys, threading, signal from subprocess import Popen, PIPE, STDOUT try: import json as serialize except: import simplejson as serialize module_dir = os.path.dirname(os.path.realpath(__file__)) base_dir = os.path.dirname(module_dir) def out(key, line): sys.stdout.write(str(key) + ':' + line + '\n') sys.stdout.flush() # Signal dispatcher started out(0, '==') def input_reader(): global process id = process.pid while True: line = process.stdout.readline() if not line: break out(id, line.rstrip()) process.wait() out(id, '/%d' % process.returncode) process = None def kill(): """Kill subprocesses (well, interrupt actually). """ if process: os.killpg(process.pid, signal.SIGINT) process = None while True: line = sys.stdin.readline() if line: line = line.rstrip() else: # Controlling process died break cmdx = line.split(None, 1) cmd = cmdx[0] response = '' if cmd in ('archin', 'larchify', 'live_iso', 'live_part', 'boot_iso', 'test'): # Start a larch script, together with a thread to read from it. # The arguments are passed as a serialized list if process: response = ("!*** Bug (Dispatcher ERROR):" " process already running (%d)" % process.pid) else: cmdx2 = cmdx[1].split(':', 1) cmds = ([base_dir + '/cli/%s.py' % cmd, '-s'] + serialize.loads(cmdx2[1])) process = Popen(cmds, preexec_fn=os.setpgrp, # to facilitate interruption cwd=cmdx2[0], # set to project directory stdin=PIPE, stdout=PIPE, stderr=STDOUT) t = threading.Thread(target=input_reader, args=()) t.start() elif cmd.startswith('??'): process.stdin.write(cmd + '\n') process.stdin.flush() elif cmd == 'kill': kill() elif cmd != 'quit': response = "!*** Bug (Dispatcher command): " + line sys.stderr.write(response + '\n!+\n') sys.stderr.flush() if cmd == 'quit': break kill()