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):
|
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:
|
Usage:
|
||||||
with log_output('logfile.txt', 'w'):
|
# Spawns the daemon
|
||||||
# do things ... output will be logged.
|
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:
|
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
|
# do things ... output will be logged
|
||||||
# and also printed to stdout.
|
# and also printed to stdout.
|
||||||
|
|
||||||
Opens a stream in 'w' mode at instance creation and closes
|
Opens a stream in 'w' mode at daemon spawning and closes it at daemon joining.
|
||||||
it at instance deletion
|
|
||||||
If echo is True, also prints the output to stdout.
|
If echo is True, also prints the output to stdout.
|
||||||
"""
|
"""
|
||||||
def __init__(self, filename, echo=False, force_color=False, debug=False):
|
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.directAssignment = False
|
||||||
self.read, self.write = os.pipe()
|
self.read, self.write = os.pipe()
|
||||||
|
|
||||||
# Spawn a daemon that writes what it reads from a pipe
|
# Sets a daemon that writes to file what it reads from a pipe
|
||||||
self.p = multiprocessing.Process(target=self._forward_redirected_pipe, args=(self.read,), name='logger_daemon')
|
self.p = multiprocessing.Process(target=self._spawn_writing_daemon, args=(self.read,), name='logger_daemon')
|
||||||
self.p.daemon = True
|
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()
|
self.parent_pipe, self.child_pipe = multiprocessing.Pipe()
|
||||||
|
|
||||||
def acquire(self):
|
def __enter__(self):
|
||||||
self.p.start()
|
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.parent_pipe.send(True)
|
||||||
self.p.join(60.0) # 1 minute to join the child
|
self.p.join(60.0) # 1 minute to join the child
|
||||||
|
|
||||||
def __enter__(self):
|
def _spawn_writing_daemon(self, read):
|
||||||
"""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):
|
|
||||||
# Parent: read from child, skip the with block.
|
# Parent: read from child, skip the with block.
|
||||||
read_file = os.fdopen(read, 'r', 0)
|
read_file = os.fdopen(read, 'r', 0)
|
||||||
with open(self.filename, 'w') as log_file:
|
with open(self.filename, 'w') as log_file:
|
||||||
@ -187,7 +180,26 @@ def _forward_redirected_pipe(self, read):
|
|||||||
if self.child_pipe.poll():
|
if self.child_pipe.poll():
|
||||||
break
|
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:
|
try:
|
||||||
# Save old stdout and stderr
|
# Save old stdout and stderr
|
||||||
self._stdout = os.dup(sys.stdout.fileno())
|
self._stdout = os.dup(sys.stdout.fileno())
|
||||||
@ -226,8 +238,3 @@ def __exit__(self, exc_type, exception, traceback):
|
|||||||
# restore output options.
|
# restore output options.
|
||||||
color._force_color = self._force_color
|
color._force_color = self._force_color
|
||||||
tty._debug = self._debug
|
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.log_path = log_path
|
||||||
self.env_path = env_path
|
self.env_path = env_path
|
||||||
dump_environment(env_path)
|
dump_environment(env_path)
|
||||||
log_redirection = log_output(log_path, verbose, sys.stdout.isatty(), True)
|
# Spawn a daemon that reads from a pipe and redirects everything to log_path
|
||||||
log_redirection.acquire()
|
with log_output(log_path, verbose, sys.stdout.isatty(), True) as log_redirection:
|
||||||
for phase_name, phase in zip(self.phases, self._InstallPhase_phases):
|
for phase_name, phase in zip(self.phases, self._InstallPhase_phases):
|
||||||
tty.msg('Executing phase : \'{0}\''.format(phase_name))
|
tty.msg('Executing phase : \'{0}\''.format(phase_name))
|
||||||
|
# Redirect stdout and stderr to daemon pipe
|
||||||
with log_redirection:
|
with log_redirection:
|
||||||
getattr(self, phase)(self.spec, self.prefix)
|
getattr(self, phase)(self.spec, self.prefix)
|
||||||
log_redirection.release()
|
|
||||||
self.log()
|
self.log()
|
||||||
# Run post install hooks before build stage is removed.
|
# Run post install hooks before build stage is removed.
|
||||||
spack.hooks.post_install(self)
|
spack.hooks.post_install(self)
|
||||||
|
Loading…
Reference in New Issue
Block a user