diff options
Diffstat (limited to 'client/bin/fd_stack.py')
-rwxr-xr-x | client/bin/fd_stack.py | 250 |
1 files changed, 125 insertions, 125 deletions
diff --git a/client/bin/fd_stack.py b/client/bin/fd_stack.py index c377cf05..e0f3f4c7 100755 --- a/client/bin/fd_stack.py +++ b/client/bin/fd_stack.py @@ -3,137 +3,137 @@ __author__ = """Copyright Martin J. Bligh, Andy Whitcroft, 2005, 2006""" import sys, os class fd_stack: - """a stack of fd redirects - - Redirects cause existing fd's to be pushed on the stack; restore() - causes the current set of redirects to be popped, restoring the previous - filehandle destinations. - - Note that we need to redirect both the sys.stdout type descriptor - (which print, etc use) and the low level OS numbered descriptor - which os.system() etc use. - """ - - def __init__(self, fd, filehandle): - self.fd = fd # eg 1 - self.filehandle = filehandle # eg sys.stdout - self.stack = [(fd, filehandle)] - - - def update_handle(self, new): - if (self.filehandle == sys.stdout): - sys.stdout = new - if (self.filehandle == sys.stderr): - sys.stderr = new - self.filehandle = new - - def redirect(self, filename): - """Redirect output to the specified file - - Overwrites the previous contents, if any. - """ - self.filehandle.flush() - fdcopy = os.dup(self.fd) - self.stack.append( (fdcopy, self.filehandle, 0) ) - # self.filehandle = file(filename, 'w') - if (os.path.isfile(filename)): - newfd = os.open(filename, os.O_WRONLY) - else: - newfd = os.open(filename, os.O_WRONLY | os.O_CREAT) - os.dup2(newfd, self.fd) - os.close(newfd) - self.update_handle(os.fdopen(self.fd, 'w')) - - - def tee_redirect(self, filename): - """Tee output to the specified file - - Overwrites the previous contents, if any. - """ - self.filehandle.flush() - #print_to_tty("tee_redirect to " + filename) - #where_art_thy_filehandles() - fdcopy = os.dup(self.fd) - r, w = os.pipe() - pid = os.fork() - if pid: # parent - os.close(r) - os.dup2(w, self.fd) - os.close(w) - self.stack.append( (fdcopy, self.filehandle, pid) ) - self.update_handle(os.fdopen(self.fd, 'w', 0)) - #where_art_thy_filehandles() - #print_to_tty("done tee_redirect to " + filename) - else: # child - os.close(w) - os.dup2(r, 0) - os.dup2(fdcopy, 1) - os.close(r) - os.close(fdcopy) - os.execlp('tee', 'tee', '-a', filename) - - - def restore(self): - """unredirect one level""" - self.filehandle.flush() - # print_to_tty("ENTERING RESTORE %d" % self.fd) - # where_art_thy_filehandles() - (old_fd, old_filehandle, pid) = self.stack.pop() - # print_to_tty("old_fd %d" % old_fd) - # print_to_tty("self.fd %d" % self.fd) - self.filehandle.close() # seems to close old_fd as well. - if pid: - os.waitpid(pid, 0) - # where_art_thy_filehandles() - os.dup2(old_fd, self.fd) - # print_to_tty("CLOSING FD %d" % old_fd) - os.close(old_fd) - # where_art_thy_filehandles() - self.update_handle(old_filehandle) - # where_art_thy_filehandles() - # print_to_tty("EXIT RESTORE %d" % self.fd) + """a stack of fd redirects + + Redirects cause existing fd's to be pushed on the stack; restore() + causes the current set of redirects to be popped, restoring the previous + filehandle destinations. + + Note that we need to redirect both the sys.stdout type descriptor + (which print, etc use) and the low level OS numbered descriptor + which os.system() etc use. + """ + + def __init__(self, fd, filehandle): + self.fd = fd # eg 1 + self.filehandle = filehandle # eg sys.stdout + self.stack = [(fd, filehandle)] + + + def update_handle(self, new): + if (self.filehandle == sys.stdout): + sys.stdout = new + if (self.filehandle == sys.stderr): + sys.stderr = new + self.filehandle = new + + def redirect(self, filename): + """Redirect output to the specified file + + Overwrites the previous contents, if any. + """ + self.filehandle.flush() + fdcopy = os.dup(self.fd) + self.stack.append( (fdcopy, self.filehandle, 0) ) + # self.filehandle = file(filename, 'w') + if (os.path.isfile(filename)): + newfd = os.open(filename, os.O_WRONLY) + else: + newfd = os.open(filename, os.O_WRONLY | os.O_CREAT) + os.dup2(newfd, self.fd) + os.close(newfd) + self.update_handle(os.fdopen(self.fd, 'w')) + + + def tee_redirect(self, filename): + """Tee output to the specified file + + Overwrites the previous contents, if any. + """ + self.filehandle.flush() + #print_to_tty("tee_redirect to " + filename) + #where_art_thy_filehandles() + fdcopy = os.dup(self.fd) + r, w = os.pipe() + pid = os.fork() + if pid: # parent + os.close(r) + os.dup2(w, self.fd) + os.close(w) + self.stack.append( (fdcopy, self.filehandle, pid) ) + self.update_handle(os.fdopen(self.fd, 'w', 0)) + #where_art_thy_filehandles() + #print_to_tty("done tee_redirect to " + filename) + else: # child + os.close(w) + os.dup2(r, 0) + os.dup2(fdcopy, 1) + os.close(r) + os.close(fdcopy) + os.execlp('tee', 'tee', '-a', filename) + + + def restore(self): + """unredirect one level""" + self.filehandle.flush() + # print_to_tty("ENTERING RESTORE %d" % self.fd) + # where_art_thy_filehandles() + (old_fd, old_filehandle, pid) = self.stack.pop() + # print_to_tty("old_fd %d" % old_fd) + # print_to_tty("self.fd %d" % self.fd) + self.filehandle.close() # seems to close old_fd as well. + if pid: + os.waitpid(pid, 0) + # where_art_thy_filehandles() + os.dup2(old_fd, self.fd) + # print_to_tty("CLOSING FD %d" % old_fd) + os.close(old_fd) + # where_art_thy_filehandles() + self.update_handle(old_filehandle) + # where_art_thy_filehandles() + # print_to_tty("EXIT RESTORE %d" % self.fd) def tee_output_logdir(fn): - """\ - Method decorator for a class to tee the output to the objects log_dir. - """ - def tee_logdir_wrapper(self, *args, **dargs): - self.job.stdout.tee_redirect(os.path.join(self.log_dir, 'stdout')) - self.job.stderr.tee_redirect(os.path.join(self.log_dir, 'stderr')) - try: - result = fn(self, *args, **dargs) - finally: - self.job.stderr.restore() - self.job.stdout.restore() - return result - return tee_logdir_wrapper + """\ + Method decorator for a class to tee the output to the objects log_dir. + """ + def tee_logdir_wrapper(self, *args, **dargs): + self.job.stdout.tee_redirect(os.path.join(self.log_dir, 'stdout')) + self.job.stderr.tee_redirect(os.path.join(self.log_dir, 'stderr')) + try: + result = fn(self, *args, **dargs) + finally: + self.job.stderr.restore() + self.job.stdout.restore() + return result + return tee_logdir_wrapper def __mark(filename, msg): - file = open(filename, 'a') - file.write(msg) - file.close() + file = open(filename, 'a') + file.write(msg) + file.close() def tee_output_logdir_mark(fn): - def tee_logdir_mark_wrapper(self, *args, **dargs): - mark = self.__class__.__name__ + "." + fn.__name__ - outfile = os.path.join(self.log_dir, 'stdout') - errfile = os.path.join(self.log_dir, 'stderr') - __mark(outfile, "--- START " + mark + " ---\n") - __mark(errfile, "--- START " + mark + " ---\n") - self.job.stdout.tee_redirect(outfile) - self.job.stderr.tee_redirect(errfile) - try: - result = fn(self, *args, **dargs) - finally: - self.job.stderr.restore() - self.job.stdout.restore() - __mark(outfile, "--- END " + mark + " ---\n") - __mark(errfile, "--- END " + mark + " ---\n") - - return result - - tee_logdir_mark_wrapper.__name__ = fn.__name__ - return tee_logdir_mark_wrapper + def tee_logdir_mark_wrapper(self, *args, **dargs): + mark = self.__class__.__name__ + "." + fn.__name__ + outfile = os.path.join(self.log_dir, 'stdout') + errfile = os.path.join(self.log_dir, 'stderr') + __mark(outfile, "--- START " + mark + " ---\n") + __mark(errfile, "--- START " + mark + " ---\n") + self.job.stdout.tee_redirect(outfile) + self.job.stderr.tee_redirect(errfile) + try: + result = fn(self, *args, **dargs) + finally: + self.job.stderr.restore() + self.job.stdout.restore() + __mark(outfile, "--- END " + mark + " ---\n") + __mark(errfile, "--- END " + mark + " ---\n") + + return result + + tee_logdir_mark_wrapper.__name__ = fn.__name__ + return tee_logdir_mark_wrapper |