Detect when a .do script deletes its stdout tmp file.
This can happen if we create the .tmp file in the same directory as the target, and the .do file first does "rm -rf" on that directory, then re-creates it. The result is that the stdout file is lost. We'll make this a warning if the .do script *didn't* write to stdout (so the loss is harmless, just weird), and an error if they *did* write to stdout, which we can detect because we still have an open fd on the file, so we can fstat() it.
This commit is contained in:
parent
2b4fe812e2
commit
1f79bf1174
5 changed files with 43 additions and 3 deletions
|
|
@ -344,8 +344,17 @@ class _BuildJob(object):
|
||||||
before_t = self.before_t
|
before_t = self.before_t
|
||||||
after_t = _try_stat(t)
|
after_t = _try_stat(t)
|
||||||
st1 = os.fstat(f.fileno())
|
st1 = os.fstat(f.fileno())
|
||||||
|
st1b = _try_stat(self.tmpname1)
|
||||||
st2 = _try_stat(self.tmpname2)
|
st2 = _try_stat(self.tmpname2)
|
||||||
if (after_t and
|
if not st1.st_size and not st1b:
|
||||||
|
warn("%s: %s deleted %s; don't do that.\n"
|
||||||
|
% (_nice(t), argv[2], self.tmpname1))
|
||||||
|
# not fatal, continue
|
||||||
|
if st1.st_size > 0 and not st1b:
|
||||||
|
err('%s: %s wrote to stdout but deleted %s.\n'
|
||||||
|
% (_nice(t), argv[2], self.tmpname1))
|
||||||
|
rv = 207
|
||||||
|
elif (after_t and
|
||||||
(not before_t or before_t.st_mtime != after_t.st_mtime) and
|
(not before_t or before_t.st_mtime != after_t.st_mtime) and
|
||||||
not stat.S_ISDIR(after_t.st_mode)):
|
not stat.S_ISDIR(after_t.st_mode)):
|
||||||
err('%s modified %s directly!\n' % (argv[2], t))
|
err('%s modified %s directly!\n' % (argv[2], t))
|
||||||
|
|
@ -365,11 +374,15 @@ class _BuildJob(object):
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
dnt = os.path.dirname(t)
|
dnt = os.path.dirname(t)
|
||||||
if not os.path.exists(dnt):
|
if not os.path.exists(dnt):
|
||||||
|
# This could happen, so report a simple error message
|
||||||
|
# that gives a hint for how to fix your .do script.
|
||||||
err('%s: target dir %r does not exist!\n' % (t, dnt))
|
err('%s: target dir %r does not exist!\n' % (t, dnt))
|
||||||
else:
|
else:
|
||||||
|
# I don't know why this would happen, so raise the
|
||||||
|
# full exception if it ever does.
|
||||||
err('%s: rename %s: %s\n' % (t, self.tmpname2, e))
|
err('%s: rename %s: %s\n' % (t, self.tmpname2, e))
|
||||||
raise
|
raise
|
||||||
os.unlink(self.tmpname1)
|
unlink(self.tmpname1)
|
||||||
elif st1.st_size > 0:
|
elif st1.st_size > 0:
|
||||||
try:
|
try:
|
||||||
os.rename(self.tmpname1, t)
|
os.rename(self.tmpname1, t)
|
||||||
|
|
|
||||||
1
t/202-del/.gitignore
vendored
1
t/202-del/.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
deltest2
|
deltest2
|
||||||
|
/destruct
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
redo deltest deltest2
|
redo deltest deltest2 deltest3
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
rm -rf destruct
|
||||||
rm -f deltest2 *~ .*~
|
rm -f deltest2 *~ .*~
|
||||||
|
|
|
||||||
25
t/202-del/deltest3.do
Normal file
25
t/202-del/deltest3.do
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
rm -rf destruct
|
||||||
|
mkdir destruct
|
||||||
|
cd destruct
|
||||||
|
cat >destruct1.do <<-EOF
|
||||||
|
rm -f *.tmp
|
||||||
|
echo 'redir' >\$3
|
||||||
|
EOF
|
||||||
|
cat >destruct2.do <<-EOF
|
||||||
|
rm -f *.tmp
|
||||||
|
echo 'stdout'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# deleting unused stdout file is a warning only
|
||||||
|
redo destruct1 2>destruct1.log || exit 11
|
||||||
|
[ "$(cat destruct1)" = "redir" ] || exit 12
|
||||||
|
|
||||||
|
# deleting *used* stdout file may be a fatal mistake,
|
||||||
|
# but we won't enforce that, since some redo variants
|
||||||
|
# might be more accepting or use different tmp file
|
||||||
|
# algorithms. So either the file should be correct,
|
||||||
|
# or it should be missing.
|
||||||
|
redo destruct2 2>destruct2.log || :
|
||||||
|
if [ -e "destruct2" ]; then
|
||||||
|
[ "$(cat destruct2)" = "stdout" ] || exit 22
|
||||||
|
fi
|
||||||
Loading…
Add table
Add a link
Reference in a new issue