From 01a036ff09bc7c283a89b23c7e24d7a33d7a4ed7 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Fri, 31 Oct 2003 13:22:54 +0000 Subject: [PATCH] Simplified implementation of saving.SaveFilter by using the new processes.PipeThroughCommand class. The child_run() method of SaveFilter is no longer supported. In processes.PipeThroughCommand, a None input stream gets /dev/null instead of inheriting its parent's stream. The class has a new run_child_with_streams to make overriding the behaviour easier. git-svn-id: https://rox.svn.sourceforge.net/svnroot/rox/trunk/ROX-Lib2@3211 66de3db3-b00d-0410-b41b-f4738ad19bea --- Help/Changes | 9 +++++++ python/rox/processes.py | 19 ++++++++++---- python/rox/saving.py | 69 ++++--------------------------------------------- 3 files changed, 28 insertions(+), 69 deletions(-) diff --git a/Help/Changes b/Help/Changes index 233bf2e..caa4d51 100644 --- a/Help/Changes +++ b/Help/Changes @@ -3,6 +3,15 @@ by Thomas Leonard http://rox.sourceforge.net +31-Oct-2003 +~~~~~~~~~~~ +Simplified implementation of saving.SaveFilter by using the new +processes.PipeThroughCommand class. The child_run() method of SaveFilter +is no longer supported. +In processes.PipeThroughCommand, a None input stream gets /dev/null instead +of inheriting its parent's stream. The class has a new run_child_with_streams +to make overriding the behaviour easier. + 29-Oct-2003 ~~~~~~~~~~~ Changed 'Dismiss' to 'Close' (Chris Shaffer). diff --git a/python/rox/processes.py b/python/rox/processes.py index 38adda2..15f6fd9 100644 --- a/python/rox/processes.py +++ b/python/rox/processes.py @@ -222,23 +222,32 @@ class PipeThroughCommand(Process): self.tmp_stream = None def child_run(self): - src = self.src + """Assigns file descriptors and calls child_run_with_streams.""" + src = self.src or file('/dev/null', 'r') - if src: - os.dup2(src.fileno(), 0) - _keep_on_exec(0) + os.dup2(src.fileno(), 0) + _keep_on_exec(0) + try: os.lseek(0, 0, 0) # OpenBSD needs this, dunno why + except: + pass + if self.dst: os.dup2(self.tmp_stream.fileno(), 1) _keep_on_exec(1) + self.child_run_with_streams() + os._exit(1) + + def child_run_with_streams(self): + """This is run by the child process. stdin and stdout have already been set up. + Should call exec() or os._exit() to finish. Default method execs self.command.""" # (basestr is python2.3 only) if isinstance(self.command, str): if os.system(self.command) == 0: os._exit(0) # No error code or signal else: os.execvp(self.command[0], self.command) - os._exit(1) def parent_post_fork(self): if self.dst and self.tmp_stream is self.dst: diff --git a/python/rox/saving.py b/python/rox/saving.py index c983f8d..a441a30 100644 --- a/python/rox/saving.py +++ b/python/rox/saving.py @@ -561,72 +561,13 @@ class SaveFilter(Saveable): self.stdin = None def save_to_stream(self, stream): - from processes import Process - from cStringIO import StringIO - errors = StringIO() - done = [] + from processes import PipeThroughCommand - # Get the FD for the output, creating a tmp file if needed - if hasattr(stream, 'fileno'): - stdout_fileno = stream.fileno() - tmp = None - else: - import tempfile - tmp = tempfile.TemporaryFile() - stdout_fileno = tmp.fileno() - - # Get the FD for the input - if self.stdin: - stdin_fileno = self.stdin.fileno() - self.stdin.seek(0) - else: - stdin_fileno = os.open('/dev/null', os.O_RDONLY) - - class FilterProcess(Process): - def child_post_fork(self): - if stdout_fileno != 1: - os.dup2(stdout_fileno, 1) - os.close(stdout_fileno) - if stdin_fileno is not None and stdin_fileno != 0: - os.dup2(stdin_fileno, 0) - os.close(stdin_fileno) - def got_error_output(self, data): - errors.write(data) - def child_died(self, status): - done.append(status) - g.mainquit() - def child_run(proc): - self.child_run() - self.process = FilterProcess() - self.killed = 0 - self.process.start() - while not done: - g.mainloop() + assert not hasattr(self, 'child_run') # No longer supported + + self.process = PipeThroughCommand(self.command, self.stdin, stream) + self.process.wait() self.process = None - status = done[0] - if self.killed: - print >> errors, '\nProcess terminated at user request' - error = errors.getvalue().strip() - if error: - raise AbortSave(error) - if status: - raise AbortSave('child_run() returned an error code, but no error message!') - if tmp: - # Data went to a temp file - tmp.seek(0) - stream.write(tmp.read()) - - def child_run(self): - """This is run in the child process. The default method runs 'self.command' - using os.system() and prints a message to stderr if the exit code is non-zero. - DO NOT call gtk functions here! - - Be careful to escape shell special characters when inserting filenames! - """ - command = self.command - if os.system(command): - print >>sys.stderr, "Command:\n%s\nreturned an error code" % command - os._exit(0) # Writing to stderr indicates error... def save_cancelled(self): """Send SIGTERM to the child processes.""" -- 2.11.4.GIT