def start(self): """Run the thread.""" for key, value in self.env.items(): logger.debug("%s=\"%s\"", key, value) logger.debug(" ".join(self.wrapper_command)) if self.terminal: terminal = system.find_executable(self.terminal) if not terminal: logger.error("Couldn't find terminal %s", self.terminal) return script_path = get_terminal_script(self.wrapper_command, self.cwd, self.env) self.game_process = self.execute_process( [terminal, "-e", script_path]) else: env = self.get_child_environment() self.game_process = self.execute_process(self.wrapper_command, env) if not self.game_process: logger.error("No game process available") return GLib.child_watch_add(self.game_process.pid, self.on_stop) # make stdout nonblocking. fileno = self.game_process.stdout.fileno() fcntl.fcntl(fileno, fcntl.F_SETFL, fcntl.fcntl(fileno, fcntl.F_GETFL) | os.O_NONBLOCK) self.stdout_monitor = GLib.io_add_watch( self.game_process.stdout, GLib.IO_IN | GLib.IO_HUP, self.on_stdout_output, )
def __tag_editor_search(self, editors=TAG_EDITORS): """ Search for tag editor """ # Search for available tag editors if not self.__tag_editor and editors: editor = editors.pop(0) if GLib.find_program_in_path("flatpak-spawn") is not None: argv = [ "flatpak-spawn", "--host", "sh", "-c", 'command -v %s' % editor ] elif GLib.find_program_in_path(editor) is not None: self.__tag_editor = editor return try: (pid, stdin, stdout, stderr) = GLib.spawn_async( argv, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.STDOUT_TO_DEV_NULL | GLib.SpawnFlags.DO_NOT_REAP_CHILD, standard_input=False, standard_output=False, standard_error=False) GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, self.__on_tag_editor_result, editor, editors) except: self.__on_tag_editor_result(None, 1, editor, editors)
def spawn(self, command: str, working_dir: Path, stdout_cb: Callable, use_sudo: True) -> bool: if use_sudo: command = f"{shutil.which('sudo')} -p '{SUDO_PROMPT_TEXT}' -S " + command (success, pid, stdin, stdout, stderr) = GLib.spawn_async_with_pipes( str(working_dir), shlex.split(command), [k + '=' + v for k, v in os.environ.items()], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None) if success: if use_sudo: sudo_pwd = self.get_sudo_pwd() if sudo_pwd is None: sudo_pwd = password_prompt_dialog( self.props.active_window, 'Please enter sudo password', 'Sudo password') if sudo_pwd is not None: self.set_sudo_pwd(sudo_pwd) if sudo_pwd is None: sudo_pwd = '' os.write(stdin, f"{sudo_pwd}\r".encode('utf-8')) os.close(stdin) def callback(*args, **kwargs): cmd_out = None with os.fdopen(stdout) as out: cmd_out = out.read() stdout_cb(cmd_out) GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, callback) return success
def __init__(self, args): '''Initialize controller and start child process The parameter args is a list of command line arguments to pass on to the child process. The "-v" argument is automatically added.''' GObject.GObject.__init__(self) # Initialize state variables self._inhibited = False self._temperature = 0 self._period = 'Unknown' self._location = (0.0, 0.0) # Start redshift with arguments args.insert(0, os.path.join(defs.BINDIR, 'redshift')) if '-v' not in args: args.insert(1, '-v') # Start child process with C locale so we can parse the output env = os.environ.copy() env['LANG'] = env['LANGUAGE'] = env['LC_ALL'] = env['LC_MESSAGES'] = 'C' self._process = GLib.spawn_async(args, envp=['{}={}'.format(k,v) for k, v in env.items()], flags=GLib.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) # Wrap remaining contructor in try..except to avoid that the child # process is not closed properly. try: # Handle child input # The buffer is encapsulated in a class so we # can pass an instance to the child callback. class InputBuffer(object): buf = '' self._input_buffer = InputBuffer() self._error_buffer = InputBuffer() self._errors = '' # Set non blocking fcntl.fcntl(self._process[2], fcntl.F_SETFL, fcntl.fcntl(self._process[2], fcntl.F_GETFL) | os.O_NONBLOCK) # Add watch on child process GLib.child_watch_add(GLib.PRIORITY_DEFAULT, self._process[0], self._child_cb) GLib.io_add_watch(self._process[2], GLib.PRIORITY_DEFAULT, GLib.IO_IN, self._child_data_cb, (True, self._input_buffer)) GLib.io_add_watch(self._process[3], GLib.PRIORITY_DEFAULT, GLib.IO_IN, self._child_data_cb, (False, self._error_buffer)) # Signal handler to relay USR1 signal to redshift process def relay_signal_handler(signal): os.kill(self._process[0], signal) return True GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGUSR1, relay_signal_handler, signal.SIGUSR1) except: self.termwait() raise
def execute(self): if self.command is None: return # Initialize pipe popen_args = { 'cwd' : self.cwd, 'shell': self.flags & self.CAPTURE_NEEDS_SHELL, 'env' : self.env } if self.input_text is not None: popen_args['stdin'] = subprocess.PIPE if self.flags & self.CAPTURE_STDOUT: popen_args['stdout'] = subprocess.PIPE if self.flags & self.CAPTURE_STDERR: popen_args['stderr'] = subprocess.PIPE self.tried_killing = False self.idle_write_id = 0 self.read_buffer = '' try: self.pipe = subprocess.Popen(self.command, **popen_args) except OSError as e: self.pipe = None self.emit('stderr-line', _('Could not execute command: %s') % (e, )) return # Signal self.emit('begin-execute') if self.flags & self.CAPTURE_STDOUT: # Set non blocking flags = fcntl.fcntl(self.pipe.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK fcntl.fcntl(self.pipe.stdout.fileno(), fcntl.F_SETFL, flags) GLib.io_add_watch(self.pipe.stdout, GObject.IO_IN | GObject.IO_HUP, self.on_output) if self.flags & self.CAPTURE_STDERR: # Set non blocking flags = fcntl.fcntl(self.pipe.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK fcntl.fcntl(self.pipe.stderr.fileno(), fcntl.F_SETFL, flags) GLib.io_add_watch(self.pipe.stderr, GObject.IO_IN | GObject.IO_HUP, self.on_output) # IO if self.input_text is not None: # Write async, in chunks of something self.write_buffer = self.input_text if self.idle_write_chunk(): self.idle_write_id = GLib.idle_add(self.idle_write_chunk) # Wait for the process to complete GLib.child_watch_add(self.pipe.pid, self.on_child_end)
def __init__(self, argv, finish_callback, timeout_s, stdin=None, env=None): self.stdout = [] self.stderr = [] self.stdin = [] self.timeout = False self.killed = False self.finished = False self.finish_callback = finish_callback # FIXME: No byte string support self.output_debug("AsyncCommand:", argv) flags = (GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_DO_NOT_REAP_CHILD) kwargs = {} if env is not None: kwargs['envp'] = env pid, stdin_fd, stdout_fd, stderr_fd = \ GLib.spawn_async(argv, standard_output=True, standard_input=True, standard_error=True, flags=flags, **kwargs) if stdin: self.stdin[:] = self._split_string(stdin, self.max_input_buf) in_io_flags = GLib.IO_OUT | GLib.IO_ERR | GLib.IO_HUP | GLib.IO_NVAL GLib.io_add_watch(stdin_fd, in_io_flags, self._in_io_callback, self.stdin) else: os.close(stdin_fd) io_flags = GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP | GLib.IO_NVAL GLib.io_add_watch(stdout_fd, io_flags, self._io_callback, self.stdout) GLib.io_add_watch(stderr_fd, io_flags, self._io_callback, self.stderr) self.pid = pid GLib.child_watch_add(pid, self._child_callback) if timeout_s is not None: GLib.timeout_add_seconds(timeout_s, self._timeout_callback)
def start_session(self, host, port, session, username, password, wait): """ Start a session using x2go """ # Start in the background and attach a watch for when it exits cmd = [ os.path.join(softwarecenter.paths.datadir, softwarecenter.paths.X2GO_HELPER) ] (self.helper_pid, stdin, stdout, stderr) = GLib.spawn_async(cmd, standard_input=True, standard_output=True, standard_error=True, flags=GObject.SPAWN_DO_NOT_REAP_CHILD) self.helper_stdin = os.fdopen(stdin, "w") self.helper_stdout = os.fdopen(stdout) self.helper_stderr = os.fdopen(stderr) # Add a watch for when the process exits GLib.child_watch_add(GLib.PRIORITY_DEFAULT, self.helper_pid, self._on_x2go_exit) # Add a watch on stdout channel = GLib.IOChannel.unix_new(self.helper_stdout) GLib.io_add_watch(channel, GLib.PRIORITY_DEFAULT, GObject.IO_IN, self._on_x2go_activity) # Start the connection self.state = "connecting" self.helper_stdin.write( "CONNECT: \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n" % (host, port, username, password, session)) self.helper_stdin.flush()
def spawn_child(argv, respawn=True, display=None): """ Spawn argv in the mainloop and keeping it as a child process (it will be made sure to exit with the parent). @respawn: If True, respawn if child dies abnormally raises utils.SpawnError returns pid """ flags = (GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_DO_NOT_REAP_CHILD) envp = [] if display: # environment is passed as a sequence of strings envd = os.environ.copy() envd['DISPLAY'] = display envp[:] = ['='.join((k,v)) for k,v in list(envd.items())] try: pid, stdin_fd, stdout_fd, stderr_fd = \ GLib.spawn_async(argv, envp,flags=flags, child_setup=_try_register_pr_pdeathsig, ) except GLib.GError as exc: raise SpawnError(str(exc)) if pid: GLib.child_watch_add(pid, _on_child_exit, (argv, respawn)) return pid
def test_exception_handling(self): pipe_r, pipe_w = os.pipe() pid = os.fork() if pid == 0: os.close(pipe_w) select.select([pipe_r], [], []) os.close(pipe_r) os._exit(1) def child_died(pid, status, loop): loop.quit() raise Exception("deadbabe") loop = GLib.MainLoop() GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop) os.close(pipe_r) os.write(pipe_w, b"Y") os.close(pipe_w) with capture_exceptions() as exc: loop.run() assert len(exc) == 1 assert exc[0].type is Exception assert exc[0].value.args[0] == "deadbabe"
def start(self): """Run the thread.""" logger.debug("Running %s", " ".join(self.wrapper_command)) for key, value in self.env.items(): logger.debug("ENV: %s=\"%s\"", key, value) if self.terminal: self.game_process = self.run_in_terminal() else: env = self.get_child_environment() self.game_process = self.execute_process(self.wrapper_command, env) if not self.game_process: logger.warning("No game process available") return GLib.child_watch_add(self.game_process.pid, self.on_stop) # make stdout nonblocking. fileno = self.game_process.stdout.fileno() fcntl.fcntl(fileno, fcntl.F_SETFL, fcntl.fcntl(fileno, fcntl.F_GETFL) | os.O_NONBLOCK) self.stdout_monitor = GLib.io_add_watch( self.game_process.stdout, GLib.IO_IN | GLib.IO_HUP, self.on_stdout_output, )
def _create_activity(self): if self._handle.activity_id is None: self._handle.activity_id = create_activity_id() self._shell.NotifyLaunch( self._service_name, self._handle.activity_id, reply_handler=self._no_reply_handler, error_handler=self._notify_launch_error_handler) environ = get_environment(self._bundle) (log_path, log_file) = open_log_file(self._bundle) command = get_command(self._bundle, self._handle.activity_id, self._handle.object_id, self._handle.uri, self._handle.invited) dev_null = file('/dev/null', 'r') child = subprocess.Popen([str(s) for s in command], env=environ, cwd=str(self._bundle.get_path()), close_fds=True, stdin=dev_null.fileno(), stdout=log_file.fileno(), stderr=log_file.fileno()) GLib.child_watch_add(child.pid, _child_watch_cb, (log_file, self._handle.activity_id))
def _run_lintian(self, filename): buf = self.textview_lintian_output.get_buffer() if not os.path.exists("/usr/bin/lintian"): buf.set_text( _("No lintian available.\n" "Please install using sudo apt-get install lintian")) return buf.set_text(_("Running lintian...")) self._lintian_output = "" self._lintian_exit_status = None self._lintian_exit_status_gathered = None cmd = ["/usr/bin/lintian", filename] (pid, stdin, stdout, stderr) = GLib.spawn_async(cmd, flags=GObject.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) for fd in [stdout, stderr]: channel = GLib.IOChannel(filedes=fd) channel.set_flags(GLib.IOFlags.NONBLOCK) GLib.io_add_watch(channel, GLib.PRIORITY_DEFAULT, GLib.IOCondition.IN | GLib.IO_ERR | GLib.IO_HUP, self._on_lintian_output) GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, self._on_lintian_finished)
def run(self, cmd): # only useful for debugging if "SOFTWARE_CENTER_DISABLE_SPAWN_HELPER" in os.environ: return self._cmd = cmd (pid, stdin, stdout, stderr) = GLib.spawn_async(cmd, flags=GObject.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) if (Globals.DEBUG_SWITCH): LOG.debug("running: '%s' as pid: '%s'" % (cmd, pid)) # python-gobject >= 3.7.3 has changed some API in incompatible # ways, so we need to check the version for which one to use. if gi_version < (3, 7, 3): self._child_watch = GLib.child_watch_add(pid, self._helper_finished, (stdout, stderr)) self._io_watch = GLib.io_add_watch(stdout, GObject.IO_IN, self._helper_io_ready, (stdout, )) else: self._child_watch = GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, self._helper_finished, data=(stdout, stderr)) self._io_watch = GLib.io_add_watch(stdout, GLib.PRIORITY_DEFAULT, GObject.IO_IN, self._helper_io_ready, (stdout, ))
def generate_avi(self): folder_png = self.animation.get_png_dir() list_file = os.path.join(folder_png, "list") video_file = self.animation.get_avi_file() framerate = self.animation.get_framerate() if not os.path.exists(list_file): error_dlg = Gtk.MessageDialog( transient_for=self.dialog, title="Cannot continue", modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, text="In directory: %s there is no listing file" % (folder_png)) error_dlg.run() error_dlg.destroy() return if not self.converterpath: error_dlg = Gtk.MessageDialog( transient_for=self.dialog, title="Cannot continue", modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, text="Cannot find ffmpeg video conversion utility") error_dlg.run() error_dlg.destroy() return self.spinner.start() # calling ffmpeg # https://trac.ffmpeg.org/wiki/Concatenate # https://trac.ffmpeg.org/wiki/Encode/VP9 call = [ self.converterpath, "-nostdin", "-y", "-loglevel", "error", "-hide_banner", "-r", str(framerate), "-f", "concat", "-safe", "0", "-i", list_file ] if self.animation.get_redblue(): call.extend(["-vf", "colorchannelmixer=rr=0:rb=1:br=1:bb=0"]) call.extend([ "-c:v", "libvpx-vp9", "-crf", "30", "-b:v", "0", "-r", str(framerate), video_file ]) self.pid, fd_in, fd_out, fd_err = GLib.spawn_async( call, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD, standard_output=False, standard_error=True) self.fh_err = os.fdopen(fd_err, "r") GLib.child_watch_add(GLib.PRIORITY_DEFAULT, self.pid, self.video_complete) GLib.io_add_watch(self.fh_err, GLib.PRIORITY_DEFAULT, GLib.IOCondition.IN, self.video_error)
def _open_link(self, tag): """Open linked file in editor.""" path = aeidon.util.shell_quote(tag.gaupol_path) command = string.Template(gaupol.conf.debug.text_editor) command = command.safe_substitute(LINENO=tag.gaupol_lineno, FILE=path) process = aeidon.util.start_process(command) GLib.child_watch_add(process.pid, self._on_editor_exit, command) tag.props.foreground = "purple"
def run(self, cmd): self.p = subprocess.Popen(cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE) if self.p: GLib.child_watch_add(self.p.pid,self._on_done) return True else: return False
def child_watch_add(priority, pid, on_closed, data): if (GLib.MAJOR_VERSION, GLib.MINOR_VERSION) < (2, 30): return GLib.child_watch_add(priority, pid, on_closed, data) else: return GLib.child_watch_add(priority=priority, pid=pid, function=on_closed, data=data)
def spawn_man_read(self): params = ['man', self.builder('entrycommandname').get_text()] def scroll_to_end(textview): i = textview.props.buffer.get_end_iter() mark = textview.props.buffer.get_insert() textview.props.buffer.place_cursor(i) textview.scroll_to_mark(mark, 0.0, True, 0.0, 1.0) def write_to_textview(io, condition, tw): if condition is GLib.IO_HUP: GLib.source_remove(self.source_id_out) GLib.source_remove(self.source_id_err) self.builder('spinner1').stop() return False line = io.readline() tw.props.buffer.insert_at_cursor(line) #time consumer, but good for attraction: #scroll_to_end(tw) while Gtk.events_pending(): Gtk.main_iteration_do(False) return True self.pid, stdin, stdout, stderr = GLib.spawn_async( params, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) self.builder('spinner1').start() io = GLib.IOChannel(stdout) err = GLib.IOChannel(stderr) self.source_id_out = io.add_watch(GLib.IO_IN | GLib.IO_HUP, write_to_textview, self.tw_out, priority=GLib.PRIORITY_HIGH) self.source_id_err = err.add_watch(GLib.IO_IN | GLib.IO_HUP, write_to_textview, self.tw_err, priority=GLib.PRIORITY_HIGH) timeout_id = GLib.timeout_add(100, self.update_progress) def closure_func(pid, status, data): GLib.spawn_close_pid(pid) GLib.source_remove(timeout_id) self.builder('spinner1').stop() self.pid = None GLib.child_watch_add(self.pid, closure_func, None)
def manage_script(self, address, node, process): if address not in self.scripts: self.scripts[address] = {} if node in self.scripts[address]: self.scripts[address][node].terminate() self.scripts[address][node] = process GLib.child_watch_add(process.pid, self.on_script_closed, (address, node))
def testChildWatch(self): self.data = None self.loop = GLib.MainLoop() argv = [sys.executable, '-c', 'import sys'] pid, stdin, stdout, stderr = GLib.spawn_async( argv, flags=GLib.SPAWN_DO_NOT_REAP_CHILD) pid.close() GLib.child_watch_add(pid, self._child_watch_cb, 12345) self.loop.run() self.assertEqual(self.data, 12345)
def process(self, widget, data=None): params = ['powershell',] def scroll_to_end(textview): i = textview.props.buffer.get_end_iter() mark = textview.props.buffer.get_insert() textview.props.buffer.place_cursor(i) textview.scroll_to_mark(mark, 0.0, True, 0.0, 1.0) def write_to_textview(io, condition, tw): if condition is GLib.IO_HUP: GLib.source_remove(self.source_id_out) GLib.source_remove(self.source_id_err) return False line = io.readline() tw.props.buffer.insert_at_cursor(line) scroll_to_end(tw) while Gtk.events_pending(): Gtk.main_iteration_do(False) return True self.pid, stdin, stdout, stderr = GLib.spawn_async(params, flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD, standard_output=True, # standard_input=True, standard_error=True) self.progress.set_text('poweshell') io = GLib.IOChannel(stdout) err = GLib.IOChannel(stderr) self.source_id_out = io.add_watch(GLib.IO_IN|GLib.IO_HUP, write_to_textview, self.tw_out, priority=GLib.PRIORITY_HIGH) self.source_id_err = err.add_watch(GLib.IO_IN|GLib.IO_HUP, write_to_textview, self.tw_err, priority=GLib.PRIORITY_HIGH) timeout_id = GLib.timeout_add(100, self.update_progress) def closure_func(pid, status, data): GLib.spawn_close_pid(pid) GLib.source_remove(timeout_id) self.progress.set_fraction(0.0) GLib.child_watch_add(self.pid, closure_func, None)
def spawn_program(args, reply_handler, error_handler): """Spawn the program specified by 'args' using the GLib mainloop. When the program finishes, 'reply_handler' will be called with a single argument that will be the porgram status code. If there is an error, error_handler will be called with an instance of SpawnError. """ def child_watch(pid, status): """Handle child termination.""" # pylint: disable=E1103 GLib.spawn_close_pid(pid) # pylint: enable=E1103 if os.WIFEXITED(status): status = os.WEXITSTATUS(status) reply_handler(status) else: msg = 'Child terminated abnormally, '\ 'status from waitpid is %r' % status error_handler(msg=msg, failed_to_start=False) def handle_error(gerror): """Handle error when spawning the process.""" failed_to_start = NO_SUCH_FILE_OR_DIR in gerror.message msg = 'GError is: code %r, message %r' % (gerror.code, gerror.message) error_handler(msg=msg, failed_to_start=failed_to_start) flags = GLib.SpawnFlags.DO_NOT_REAP_CHILD | \ GLib.SpawnFlags.SEARCH_PATH | \ GLib.SpawnFlags.STDOUT_TO_DEV_NULL | \ GLib.SpawnFlags.STDERR_TO_DEV_NULL pid = None bytes_args = [] for arg in args: if isinstance(arg, compat.text_type): arg = arg.encode('utf-8') if not isinstance(arg, compat.basestring): arg = compat.binary_type(arg) bytes_args.append(arg) try: pid, _, _, _ = GLib.spawn_async(argv=bytes_args, flags=flags) except GLib.GError as e: handle_error(e) else: logger.debug('Spawning the program %r with the glib mainloop ' '(returned pid is %r).', args, pid) GLib.child_watch_add(pid, child_watch)
def _edit_tag(self, action, variant): """ Run tag editor @param SimpleAction @param GVariant """ album_path = Lp.albums.get_path(self._object_id) argv = [self._tag_editor, album_path, None] (s, pid, i, o, e) = GLib.spawn_async_with_pipes( None, argv, None, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, None) GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, self._on_exit)
def start_unison(self): pid, _, idout, iderr = GLib.spawn_async( self.SYNC_COMMAND, flags=(GLib.SPAWN_DO_NOT_REAP_CHILD | GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_STDOUT_TO_DEV_NULL), standard_output=None, standard_error=True) GLib.child_watch_add(pid, self._on_done) GLib.io_add_watch(os.fdopen(iderr, 'r'), GLib.IO_IN | GLib.IO_PRI, self._on_stderr) return pid
def execute(self): if self.command is None: return # Initialize pipe popen_args = { 'cwd': self.cwd, 'shell': self.flags & self.CAPTURE_NEEDS_SHELL, 'env': self.env } if self.input_text is not None: popen_args['stdin'] = subprocess.PIPE if self.flags & self.CAPTURE_STDOUT: popen_args['stdout'] = subprocess.PIPE if self.flags & self.CAPTURE_STDERR: popen_args['stderr'] = subprocess.PIPE self.tried_killing = False self.in_channel = None self.out_channel = None self.err_channel = None self.in_channel_id = 0 self.out_channel_id = 0 self.err_channel_id = 0 try: self.pipe = subprocess.Popen(self.command, **popen_args) except OSError as e: self.pipe = None self.emit('stderr-line', _('Could not execute command: %s') % (e, )) return self.emit('begin-execute') if self.input_text is not None: self.in_channel, self.in_channel_id = self.add_in_watch(self.pipe.stdin.fileno(), self.on_in_writable) if self.flags & self.CAPTURE_STDOUT: self.out_channel, self.out_channel_id = self.add_out_watch(self.pipe.stdout.fileno(), self.on_output) if self.flags & self.CAPTURE_STDERR: self.err_channel, self.err_channel_id = self.add_out_watch(self.pipe.stderr.fileno(), self.on_err_output) # Wait for the process to complete GLib.child_watch_add(GLib.PRIORITY_DEFAULT, self.pipe.pid, self.on_child_end)
def process(self,widget,data=None): # changer le chemin de répertoire chemin = self.label_destination.get_text() print(chemin) os.chdir(chemin) # Pour l'instant on a besoin de 2 paramètres # Url et Format url = self.entree.get_text() format = self.combo.get_active_text() # On utlisera youtube-dl pour télécharger la vidéo params = ['youtube-dl','-f',format, url] def scroll_to_end(textview): i = textview.props.buffer.get_end_iter() mark = textview.props.buffer.get_insert() textview.props.buffer.place_cursor(i) textview.scroll_to_mark(mark, 0.0, True, 0.0, 1.0) def write_to_textview(io, condition, tw): if condition is GLib.IO_HUP: GLib.source_remove(self.source_id_out) GLib.source_remove(self.source_id_err) return False line = io.readline() tw.props.buffer.insert_at_cursor(line) scroll_to_end(tw) while Gtk.events_pending(): Gtk.main_iteration_do(False) return True self.pid, stdin, stdout, stderr = GLib.spawn_async(params,\ flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD,\ standard_output=True,\ standard_error=True) io = GLib.IOChannel(stdout) err = GLib.IOChannel(stderr) self.source_id_out = io.add_watch(GLib.IO_IN|GLib.IO_HUP,\ write_to_textview,\ self.tw_out,\ priority=GLib.PRIORITY_HIGH) self.source_id_err = err.add_watch(GLib.IO_IN|GLib.IO_HUP,\ write_to_textview,\ self.tw_err,\ priority=GLib.PRIORITY_HIGH) timeout_id = GLib.timeout_add(100, self.update_progress) def closure_func(pid, status, data): GLib.spawn_close_pid(pid) GLib.source_remove(timeout_id) self.progress.set_fraction(0.0) GLib.child_watch_add(self.pid, closure_func, None)
def _activate_cb(self, menu, path): """ """ self._log.debug('acivate') napi_cmd = ['pynapi', '--tool-mode', path] self._log.debug('spawning command: %s', ' '.join(napi_cmd)) (pid, _, stdout, _) = GLib.spawn_async(napi_cmd, standard_output=True, flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SPAWN_DO_NOT_REAP_CHILD) GLib.child_watch_add(pid, self._pynapi_finished, stdout, GLib.PRIORITY_DEFAULT) self._log.info('pynapi started as PID %d', pid)
def run(self, devicePath): (retval, self._pid, _stdin, stdout, _stderr) = \ GLib.spawn_async_with_pipes(None, ["checkisomd5", "--gauge", devicePath], [], GLib.SpawnFlags.DO_NOT_REAP_CHILD|GLib.SpawnFlags.SEARCH_PATH, None, None) if not retval: return # This function waits for checkisomd5 to end and then cleans up after it. GLib.child_watch_add(self._pid, self._checkisoEndsCB) # This function watches the process's stdout. GLib.io_add_watch(stdout, GLib.IOCondition.IN|GLib.IOCondition.HUP, self._checkisoStdoutWatcher) self.window.run()
def run(self, cmd): r = GLib.spawn_async( cmd, flags=GLib.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True, ) self.pid, idin, idout, iderr = r fout = os.fdopen(idout, "r") ferr = os.fdopen(iderr, "r") GLib.child_watch_add(self.pid, self._on_done) GLib.io_add_watch(fout, GLib.IO_IN, self._on_stdout) GLib.io_add_watch(ferr, GLib.IO_IN, self._on_stderr) return self.pid
def create_archive(self, files, callback): temp_dir = tempfile.mkdtemp("", "ffs-") if len(files) == 1: archive_name = os.path.join(temp_dir, GLib.path_get_basename(files[0])) else: archive_name = os.path.join(temp_dir, "archive.zip") cmd = ["7z", "-y", "-tzip", "-bd", "-mx=7", "a", archive_name] flags = GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD result = GLib.spawn_async(cmd + files, [], GLib.get_current_dir(), flags, None, None, False, True, False) self.out_7z = GLib.IOChannel(result[2]) self.out_7z.set_close_on_unref(True) GLib.child_watch_add(result[0], self.on_child_process_exit, callback) return archive_name
def _edit_tag(self, action, variant): """ Run tag editor @param SimpleAction @param GVariant """ album_path = Lp().albums.get_path(self._object_id) argv = [self._tag_editor, album_path, None] (s, pid, i, o, e) = GLib.spawn_async_with_pipes( None, argv, None, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, None) GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, self._on_exit)
def watchProcess(proc, name): """Watch for a process exit, and raise a ExitError when it does. This method installs a SIGCHLD signal handler and thus interferes the child_watch_add methods in GLib. Use watchProcessGLib to convert to GLib mode if using a GLib main loop. Since the SIGCHLD handler calls wait() on the watched process, this call cannot be combined with Popen.wait() or Popen.communicate, and also doing so wouldn't make a whole lot of sense. :param proc: The Popen object for the process :param name: The name of the process """ global _watch_process_handler_set if not _watch_process_glib and not _watch_process_handler_set: signal.signal(signal.SIGCHLD, _sigchld_handler) _watch_process_handler_set = True # Add the PID to the dictionary # The second item in the list is for the GLib event source id and will be # replaced with the id once we have one. _forever_pids[proc.pid] = [name, None] # If GLib is watching processes, add a watcher. child_watch_add checks if # the process has already exited. if _watch_process_glib: _forever_pids[proc.id][1] = GLib.child_watch_add(proc.pid, _watch_process_cb, name) else: # Check that the process didn't already exit if proc.poll() is not None: del _forever_pids[proc.pid] _raise_exit_error([(name, proc.returncode)])
def watchProcess(proc, name): """Watch for a process exit, and raise a ExitError when it does. This method installs a SIGCHLD signal handler and thus interferes the child_watch_add methods in GLib. Use watchProcessGLib to convert to GLib mode if using a GLib main loop. Since the SIGCHLD handler calls wait() on the watched process, this call cannot be combined with Popen.wait() or Popen.communicate, and also doing so wouldn't make a whole lot of sense. :param proc: The Popen object for the process :param name: The name of the process """ global _watch_process_handler_set if not _watch_process_glib and not _watch_process_handler_set: signal.signal(signal.SIGCHLD, _sigchld_handler) _watch_process_handler_set = True # Add the PID to the dictionary # The second item in the list is for the GLib event source id and will be # replaced with the id once we have one. _forever_pids[proc.pid] = [name, None] # If GLib is watching processes, add a watcher. child_watch_add checks if # the process has already exited. if _watch_process_glib: _forever_pids[proc.id][1] = GLib.child_watch_add( proc.pid, _watch_process_cb, name) else: # Check that the process didn't already exit if proc.poll() is not None: del _forever_pids[proc.pid] _raise_exit_error([(name, proc.returncode)])
def add_child_handler(self, pid, callback, *args): self.remove_child_handler(pid) handle = self._create_handle_for_pid(pid) source = GLib.child_watch_add(0, handle, self.__callback__) self._sources[pid] = source, callback, args, handle self._handles[handle] = pid
def run(self): """Run the process.""" # NOTE: DO_NOT_REAP_CHILD: the child will not be automatically reaped; # you must use g_child_watch_add yourself (or call waitpid or handle `SIGCHLD` yourself), # or the child will become a zombie. # source: # http://valadoc.org/#!api=glib-2.0/GLib.SpawnFlags.DO_NOT_REAP_CHILD # NOTE: SEARCH_PATH: argv[0] need not be an absolute path, it will be looked for in the user’s PATH # source: # http://lazka.github.io/pgi-docs/#GLib-2.0/flags.html#GLib.SpawnFlags.SEARCH_PATH self.pid, self.stdin, self.stdout, self.stderr = GLib.spawn_async(self.command, flags=GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD ) logger.debug("command: ".format(self.command)) logger.debug("stdin: ".format(self.stdin)) logger.debug("stdout: ".format(self.stdout)) logger.debug("stderr: ".format(self.stderr)) logger.debug("pid: ".format(self.pid)) # close file descriptor self.pid.close() print self.stderr # NOTE: GLib.PRIORITY_HIGH = -100 # Use this for high priority event sources. # It is not used within GLib or GTK+. watch = GLib.child_watch_add(GLib.PRIORITY_HIGH, self.pid, self.exited_cb) return self.pid
def run(self, devicePath): (retval, self._pid, _stdin, stdout, _stderr) = \ GLib.spawn_async_with_pipes(None, ["checkisomd5", "--gauge", devicePath], [], GLib.SpawnFlags.DO_NOT_REAP_CHILD|GLib.SpawnFlags.SEARCH_PATH, None, None) if not retval: return # This function waits for checkisomd5 to end and then cleans up after it. GLib.child_watch_add(self._pid, self._checkisoEndsCB) # This function watches the process's stdout. GLib.io_add_watch(stdout, GLib.IOCondition.IN | GLib.IOCondition.HUP, self._checkisoStdoutWatcher) self.window.run()
def check_environment(): run_test = os.environ.get("SUGAR_RUN_TEST", None) if run_test is not None: log_path = os.environ.get("SUGAR_TEST_LOG", None) if log_path is None: log_path = os.path.join(get_logs_dir(), "test.log") log_file = open(log_path, "w") else: log_file = open(log_path, "a") test_process = subprocess.Popen(run_test, stdout=log_file, stderr=subprocess.STDOUT, shell=True) GLib.child_watch_add(test_process.pid, _test_child_watch_cb, log_file)
def _check_for_channel_updates_timer(self): """ run a background timer to see if the a-x-i data we have is still fresh or if the cache has changed since """ # this is expensive and does not need UI to we shove it out channel_update = os.path.join( softwarecenter.paths.datadir, "update-software-center-channels") (pid, stdin, stdout, stderr) = GLib.spawn_async( [channel_update], flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD) # python-gobject >= 3.7.3 has changed some API in incompatible # ways, so we need to check the version for which one to use. if gi_version < (3, 7, 3): GLib.child_watch_add(pid, self._on_check_for_channel_updates_finished) else: GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, self._on_check_for_channel_updates_finished)
def run_software_center_agent(db): """ Helper that triggers the update-software-center-agent helper and will also reopen the database on success """ def _on_update_software_center_agent_finished(pid, condition): LOG.info("software-center-agent finished with status %i" % os.WEXITSTATUS(condition)) if os.WEXITSTATUS(condition) == 0: db.reopen() # run the update sc_agent_update = os.path.join(softwarecenter.paths.datadir, "update-software-center-agent") (pid, stdin, stdout, stderr) = GLib.spawn_async( [sc_agent_update, "--datadir", softwarecenter.paths.datadir], flags=GObject.SPAWN_DO_NOT_REAP_CHILD ) # python-gobject >= 3.7.3 has changed some API in incompatible # ways, so we need to check the version for which one to use. if gi_version < (3, 7, 3): GLib.child_watch_add(pid, _on_update_software_center_agent_finished) else: GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, _on_update_software_center_agent_finished)
def test_exception_handling(self): pipe_r, pipe_w = os.pipe() pid = os.fork() if pid == 0: os.close(pipe_w) select.select([pipe_r], [], []) os.close(pipe_r) os._exit(1) def child_died(pid, status, loop): loop.quit() raise Exception("deadbabe") loop = GLib.MainLoop() GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop) os.close(pipe_r) os.write(pipe_w, _bytes("Y")) os.close(pipe_w) def excepthook(type, value, traceback): self.assertTrue(type is Exception) self.assertEqual(value.args[0], "deadbabe") sys.excepthook = excepthook try: got_exception = False try: loop.run() except: got_exception = True finally: sys.excepthook = sys.__excepthook__ # # The exception should be handled (by printing it) # immediately on return from child_died() rather # than here. See bug #303573 # self.assertFalse(got_exception)
def testExceptionHandling(self): pipe_r, pipe_w = os.pipe() pid = os.fork() if pid == 0: os.close(pipe_w) select.select([pipe_r], [], []) os.close(pipe_r) os._exit(1) def child_died(pid, status, loop): loop.quit() raise Exception("deadbabe") loop = GLib.MainLoop() GLib.child_watch_add(pid, child_died, loop) os.close(pipe_r) os.write(pipe_w, _bytes("Y")) os.close(pipe_w) def excepthook(type, value, traceback): assert type is Exception assert value.args[0] == "deadbabe" sys.excepthook = excepthook got_exception = False try: loop.run() except: got_exception = True # # The exception should be handled (by printing it) # immediately on return from child_died() rather # than here. See bug #303573 # sys.excepthook = sys.__excepthook__ assert not got_exception
def _run_lintian(self, filename): buf = self.textview_lintian_output.get_buffer() if not os.path.exists("/usr/bin/lintian"): buf.set_text( _("No lintian available.\n" "Please install using sudo apt-get install lintian")) return buf.set_text(_("Running lintian...")) self._lintian_output = "" self._lintian_exit_status = None self._lintian_exit_status_gathered = None cmd = ["/usr/bin/lintian", filename] (pid, stdin, stdout, stderr) = GLib.spawn_async( cmd, flags=GObject.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) for fd in [stdout, stderr]: channel = GLib.IOChannel(filedes=fd) channel.set_flags(GLib.IOFlags.NONBLOCK) GLib.io_add_watch(channel, GLib.PRIORITY_DEFAULT, GLib.IOCondition.IN | GLib.IO_ERR | GLib.IO_HUP, self._on_lintian_output) GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, self._on_lintian_finished)
def __init__(self, argv, cb, *cb_data): self.Log.i('cmd = %s'%str(argv)) self.cmd = argv self.exited = False flags = (GLib.SPAWN_SEARCH_PATH | GLib.SPAWN_DO_NOT_REAP_CHILD) self.pid, stdin, stdout, stderr = GLib.spawn_async(argv, flags=flags) self.cb = cb self.cb_data = cb_data def cb(pid, status, ref): spawn = ref() if spawn: spawn.watch(pid, status) self.tag = GLib.child_watch_add(self.pid, cb, weakref.ref(self))
def run(self, cmd): # only useful for debugging if "SOFTWARE_CENTER_DISABLE_SPAWN_HELPER" in os.environ: return self._cmd = cmd (pid, stdin, stdout, stderr) = GLib.spawn_async( cmd, flags=GObject.SPAWN_DO_NOT_REAP_CHILD, standard_output=True, standard_error=True) LOG.debug("running: '%s' as pid: '%s'" % (cmd, pid)) # python-gobject >= 3.7.3 has changed some API in incompatible # ways, so we need to check the version for which one to use. if gi_version < (3, 7, 3): self._child_watch = GLib.child_watch_add( pid, self._helper_finished, (stdout, stderr)) self._io_watch = GLib.io_add_watch( stdout, GObject.IO_IN, self._helper_io_ready, (stdout, )) else: self._child_watch = GLib.child_watch_add( GLib.PRIORITY_DEFAULT, pid, self._helper_finished, data=(stdout, stderr)) self._io_watch = GLib.io_add_watch( stdout, GLib.PRIORITY_DEFAULT, GObject.IO_IN, self._helper_io_ready, (stdout, ))
def _get_source(self, source_object: object, res: object, view_dict: dict): """ print the source. """ def block_run(cmd_line: list): """ Run cmd_line and block until it exits. """ # Block until process exits. subprocess.Popen(cmd_line, stdout=subprocess.PIPE).communicate() tmpfile = tempfile.NamedTemporaryFile() tmpfile.write(source_object.get_data_finish(res)) self._tmp_files.append(tmpfile) app_info = Gio.app_info_get_default_for_type('text/html', False) mp_proc = Process(target=block_run, args=([app_info.get_executable(), tmpfile.name],)) mp_proc.start() GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, mp_proc.pid, self._close_tmp, tmpfile)
def test_child_watch_no_data(self): def cb(pid, status): self.status = status self.loop.quit() self.status = None self.loop = GLib.MainLoop() argv = [sys.executable, '-c', 'import sys'] pid, stdin, stdout, stderr = GLib.spawn_async( argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD) pid.close() id = GLib.child_watch_add(GLib.PRIORITY_HIGH, pid, cb) self.assertEqual(self.loop.get_context().find_source_by_id(id).priority, GLib.PRIORITY_HIGH) self.loop.run() self.assertEqual(self.status, 0)
def watchProcessGLib(): """Convert process watching to GLib mode. This allows anaconda modes that use GLib main loops to use GLib.child_watch_add and continue to watch processes started before the main loop. """ global _watch_process_glib # The first call to child_watch_add will replace our SIGCHLD handler, and # child_watch_add checks if the process has already exited before it returns, # which will handle processes that exit while we're in the loop. _watch_process_glib = True for child_pid in _forever_pids: _forever_pids[child_pid][1] = GLib.child_watch_add(child_pid, _watch_process_cb, _forever_pids[child_pid])
def add_child_handler(self, pid, callback, *args): self.remove_child_handler(pid) def _glib_callback(pid, status): import os self._sources.pop(pid) GLib.source_remove(source) if os.WIFSIGNALED(status): returncode = -os.WTERMSIG(status) elif os.WIFEXITED(status): returncode = os.WEXITSTATUS(status) else: returncode = status callback(pid, returncode, *args) source = GLib.child_watch_add(0, pid, _glib_callback) self._sources[pid] = source
def start_session(self, host, port, session, username, password, wait): """ Start a session using x2go """ # Start in the background and attach a watch for when it exits cmd = [os.path.join(softwarecenter.paths.datadir, softwarecenter.paths.X2GO_HELPER)] (self.helper_pid, stdin, stdout, stderr) = GLib.spawn_async( cmd, standard_input=True, standard_output=True, standard_error=True, flags=GObject.SPAWN_DO_NOT_REAP_CHILD) self.helper_stdin = os.fdopen(stdin, "w") self.helper_stdout = os.fdopen(stdout) self.helper_stderr = os.fdopen(stderr) # Add a watch for when the process exits GLib.child_watch_add( GLib.PRIORITY_DEFAULT, self.helper_pid, self._on_x2go_exit) # Add a watch on stdout channel = GLib.IOChannel.unix_new(self.helper_stdout) GLib.io_add_watch(channel, GLib.PRIORITY_DEFAULT, GObject.IO_IN, self._on_x2go_activity) # Start the connection self.state = "connecting" self.helper_stdin.write( "CONNECT: \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n" % (host, port, username, password, session)) self.helper_stdin.flush()