def run(proc_specs, tty_fd, callback): argpipe_read, argpipe_write = shell_spawn.make_pipe() pipe_read, pipe_write = shell_spawn.make_pipe() proc_specs = map(reprable_spec, proc_specs) args_data = repr((proc_specs, pipe_write.fileno(), tty_fd.fileno())) # Exposes icky internal stuff in argv, visible in /proc. # Send across pipe instead? argv = ["python", __file__, str(argpipe_read.fileno())] def in_subprocess(): argpipe_write.close() os.execv(sys.executable, argv) helper_pid = shell_spawn.in_forked(in_subprocess) del argpipe_read del pipe_write # Forking and sending pids should be prompt, so we can block here. argpipe_write.write(args_data) argpipe_write.close() pids = eval(pipe_read.readline(), {}) def on_ready(*args): # TODO: This is not really safe because this reading is # buffered. It could read multiple messages but we will only # handle one. line = pipe_read.readline() if len(line) > 0: message = eval(line, {}) callback(*message) return True else: return False gobject.io_add_watch(pipe_read.fileno(), gobject.IO_IN | gobject.IO_HUP, on_ready) return helper_pid, pids
def __init__(self): self._queue = [] read_fd, self._write_fd = shell_spawn.make_pipe() def on_ready(*args): read_fd.read(1) while True: try: func = self._queue.pop(0) except IndexError: break else: func() return True # Need to initialise threads otherwise pygobject won't drop # the Python GIL while doing an iteration of the glib loop. gobject.threads_init() gobject.io_add_watch(read_fd.fileno(), gobject.IO_IN, on_ready)