Skip to content

Commit

Permalink
builder.py: atomically replace the log for a given target.
Browse files Browse the repository at this point in the history
Previously we were truncating the log if it existed.  This would cause
redo-log to produce invalid output if you had the following (admittedly
rare) sequence in a single session:
- start building X
- redo-log starts showing the log for X
- finish building X
- redo-log has not finished showing the log for X yet
- start building X again for some reason
- redo-log sees a truncated logfile.

Now, redo-log can finish reading the original file (which no longer has
a filename since it was overwritten) while the new file is being
created.
  • Loading branch information
apenwarr committed Mar 2, 2019
1 parent 8a97b0c commit 63230a1
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 4 deletions.
2 changes: 1 addition & 1 deletion bin/all.do
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
exec >&2
redo-ifchange ../redo/version/all ../redo/py list redo-sh
redo-ifchange ../redo/version/all ../redo/py ../redo/sh list
xargs redo-ifchange <list
16 changes: 13 additions & 3 deletions redo/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,20 @@ def _start_self(self):
firstline = open(os.path.join(dodir, dofile)).readline().strip()
if firstline.startswith('#!/'):
argv[0:2] = firstline[2:].split(' ')
# make sure to create the logfile *before* writing the meta() about it.
# that way redo-log won't trace into an obsolete logfile.
# make sure to create the logfile *before* writing the meta() about
# it. that way redo-log won't trace into an obsolete logfile.
#
# We open a temp file and atomically rename it into place here.
# This guarantees that redo-log will never experience a file that
# gets truncated halfway through reading (eg. if we build the same
# target more than once in a run). Similarly, we don't want to
# actually unlink() the file in case redo-log is about to start
# reading a previous instance created during this session. It
# should always see either the old or new instance.
if env.v.LOG:
open(state.logname(self.sf.id), 'w')
lfd, lfname = tempfile.mkstemp(prefix='redo.', suffix='.log.tmp')
os.fdopen(lfd, 'w')
os.rename(lfname, state.logname(self.sf.id))
dof = state.File(name=os.path.join(dodir, dofile))
dof.set_static()
dof.save()
Expand Down

0 comments on commit 63230a1

Please sign in to comment.