log : refactored acquire and release semantic to meet the context manager protocol
This commit is contained in:
parent
00b8e0b567
commit
1ecea4c2f1
@ -101,19 +101,23 @@ def __exit__(self, exc_type, exception, traceback):
|
||||
|
||||
|
||||
class log_output(object):
|
||||
"""Redirects output and error of enclosed block to a file.
|
||||
"""Spawns a daemon that reads from a pipe and writes to a file
|
||||
|
||||
Usage:
|
||||
with log_output('logfile.txt', 'w'):
|
||||
# do things ... output will be logged.
|
||||
# Spawns the daemon
|
||||
with log_output('logfile.txt', 'w') as log_redirection:
|
||||
# do things ... output is not redirected
|
||||
with log_redirection:
|
||||
# do things ... output will be logged
|
||||
|
||||
or:
|
||||
with log_output('logfile.txt', echo=True):
|
||||
with log_output('logfile.txt', echo=True) as log_redirection:
|
||||
# do things ... output is not redirected
|
||||
with log_redirection:
|
||||
# do things ... output will be logged
|
||||
# and also printed to stdout.
|
||||
|
||||
Opens a stream in 'w' mode at instance creation and closes
|
||||
it at instance deletion
|
||||
Opens a stream in 'w' mode at daemon spawning and closes it at daemon joining.
|
||||
If echo is True, also prints the output to stdout.
|
||||
"""
|
||||
def __init__(self, filename, echo=False, force_color=False, debug=False):
|
||||
@ -128,32 +132,21 @@ def __init__(self, filename, echo=False, force_color=False, debug=False):
|
||||
self.directAssignment = False
|
||||
self.read, self.write = os.pipe()
|
||||
|
||||
# Spawn a daemon that writes what it reads from a pipe
|
||||
self.p = multiprocessing.Process(target=self._forward_redirected_pipe, args=(self.read,), name='logger_daemon')
|
||||
# Sets a daemon that writes to file what it reads from a pipe
|
||||
self.p = multiprocessing.Process(target=self._spawn_writing_daemon, args=(self.read,), name='logger_daemon')
|
||||
self.p.daemon = True
|
||||
# I just need this to communicate to un-summon the daemon
|
||||
# Needed to un-summon the daemon
|
||||
self.parent_pipe, self.child_pipe = multiprocessing.Pipe()
|
||||
|
||||
def acquire(self):
|
||||
def __enter__(self):
|
||||
self.p.start()
|
||||
return log_output.OutputRedirection(self)
|
||||
|
||||
def release(self):
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.parent_pipe.send(True)
|
||||
self.p.join(60.0) # 1 minute to join the child
|
||||
|
||||
def __enter__(self):
|
||||
"""Redirect output from the with block to a file.
|
||||
|
||||
Hijacks stdout / stderr and writes to the pipe
|
||||
connected to the logger daemon
|
||||
"""
|
||||
# remember these values for later.
|
||||
self._force_color = color._force_color
|
||||
self._debug = tty._debug
|
||||
# Redirect this output to a pipe
|
||||
self._redirect_to_pipe(self.write)
|
||||
|
||||
def _forward_redirected_pipe(self, read):
|
||||
def _spawn_writing_daemon(self, read):
|
||||
# Parent: read from child, skip the with block.
|
||||
read_file = os.fdopen(read, 'r', 0)
|
||||
with open(self.filename, 'w') as log_file:
|
||||
@ -187,7 +180,26 @@ def _forward_redirected_pipe(self, read):
|
||||
if self.child_pipe.poll():
|
||||
break
|
||||
|
||||
def _redirect_to_pipe(self, write):
|
||||
def __del__(self):
|
||||
"""Closes the pipes"""
|
||||
os.close(self.write)
|
||||
os.close(self.read)
|
||||
|
||||
class OutputRedirection(object):
|
||||
def __init__(self, other):
|
||||
self.__dict__.update(other.__dict__)
|
||||
|
||||
def __enter__(self):
|
||||
"""Redirect output from the with block to a file.
|
||||
|
||||
Hijacks stdout / stderr and writes to the pipe
|
||||
connected to the logger daemon
|
||||
"""
|
||||
# remember these values for later.
|
||||
self._force_color = color._force_color
|
||||
self._debug = tty._debug
|
||||
# Redirect this output to a pipe
|
||||
write = self.write
|
||||
try:
|
||||
# Save old stdout and stderr
|
||||
self._stdout = os.dup(sys.stdout.fileno())
|
||||
@ -226,8 +238,3 @@ def __exit__(self, exc_type, exception, traceback):
|
||||
# restore output options.
|
||||
color._force_color = self._force_color
|
||||
tty._debug = self._debug
|
||||
|
||||
def __del__(self):
|
||||
"""Closes the pipes"""
|
||||
os.close(self.write)
|
||||
os.close(self.read)
|
||||
|
@ -1136,13 +1136,13 @@ def build_process():
|
||||
self.log_path = log_path
|
||||
self.env_path = env_path
|
||||
dump_environment(env_path)
|
||||
log_redirection = log_output(log_path, verbose, sys.stdout.isatty(), True)
|
||||
log_redirection.acquire()
|
||||
# Spawn a daemon that reads from a pipe and redirects everything to log_path
|
||||
with log_output(log_path, verbose, sys.stdout.isatty(), True) as log_redirection:
|
||||
for phase_name, phase in zip(self.phases, self._InstallPhase_phases):
|
||||
tty.msg('Executing phase : \'{0}\''.format(phase_name))
|
||||
# Redirect stdout and stderr to daemon pipe
|
||||
with log_redirection:
|
||||
getattr(self, phase)(self.spec, self.prefix)
|
||||
log_redirection.release()
|
||||
self.log()
|
||||
# Run post install hooks before build stage is removed.
|
||||
spack.hooks.post_install(self)
|
||||
|
Loading…
Reference in New Issue
Block a user