RFR: JDK-8207001: *.obj.log files get truncated causing unreliable incremental builds on Windows
Erik Joelsson
erik.joelsson at oracle.com
Tue Jul 10 17:37:49 UTC 2018
Please review this fix for problem 1 described below. The patch is
basically what Ralf suggested.
Bug: https://bugs.openjdk.java.net/browse/JDK-8207001
Webrev: http://cr.openjdk.java.net/~erikj/8207001/webrev.01/
/Erik
On 2018-07-10 10:34, Erik Joelsson wrote:
> Hello Ralf,
>
> Very interesting analysis! I have spent a lot of time trying to get
> the piping to log files, while keeping out/err separation working with
> as little performance impact as possible. I was aware of problem 3,
> which causes some annoying output ordering sometimes, but I had not
> encountered 1 and 2 before. Checking my latest local Windows build, I
> do indeed have some truncated files, not as many as you, but still 79
> (less virus scanning). That would certainly make incremental builds
> unreliable.
>
> I tried your suggestion for problem 1 and it works for me too. We
> should definitely get that fix in. I have filed JDK-8207001. Do you
> mind if I use your patch for it?
>
> I agree on the only solution for the 3rd problem, but I would not want
> to go there. Delaying output can have lots of weird consequences, if
> you for example interrupt a build with ctrl-c.
>
> Another option would be to revert to our previous solution, where we
> used this script:
> http://hg.openjdk.java.net/jdk8u/jdk8u/file/090b27d25e19/common/bin/logger.sh
> The problem with that was performance as it created more extra shell
> instances for each compile command.
>
> The only solution to fix problem 2 would be to stop separating
> out/err. I wonder how big of a problem that actually is though?
>
> /Erik
>
>
> On 2018-07-10 05:34, Schmelter, Ralf wrote:
>> Hi,
>>
>> while building openjdk on Windows, I've stumbled over a problem which
>> leads to truncated *.obj.log files, which in turn leads to empty
>> dependency files (which are generated from the contents of the
>> *.obj.log files on Windows). In the end, the incremental build will
>> not be reliable.
>>
>> The reason seems to be this code from the ExecuteWithLog macro in
>> common/MakeBase.gmk:
>> ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log
>> >&2) || \
>> ...
>>
>> This executes the command given in $2 and tries to write
>> stdout/stderr to the file given by $1 and to 'normal' stdout/stderr
>> via process substitution. But it has a few problems.
>>
>> The first problem occurs when the stdout-tee truncates the file, then
>> it writes some of the input it got into the file and only after this
>> the stderr-tee has run far enough to truncate the same file, which
>> leads to the loss of at least a part of stdout.
>>
>> Another problem appears when the command writes to stdout and stderr.
>> Since each tee has its own file position, they would overwrite one
>> another.
>>
>> The third problem arises because when the command $2 has ended, the
>> bash shell will not wait for the process substitutions (the two tee
>> commands) to end and instead will process the next command. Here we
>> try to copy the log file in case of an error. But the tee commands
>> might not have written the whole input they have got, so not the
>> whole content of the file might get copied.
>>
>>
>> In my case it seems to be the first problem which I see most. When
>> doing a fresh build on my Windows machine (which has quite an
>> aggressive virus scanner active), I get something like the following:
>>> find . -name "*.obj.log" -size 0 | wc -l
>> 424
>>
>>> find . -name "*.obj.log" -not -size 0 | wc -l
>> 1603
>>
>> Which means about 20% of the *.obj.log files are truncated.
>>
>> When I replace the code above with:
>> ( $(strip $2) > >($(TEE) $(strip $1).log) 2>&1 || \
>> ...
>>
>> I see no more truncated *.obj.log files. The cost is that stderr is
>> redirected to stdout (since the >&2 of the second tee is missing).
>> The last problem can be avoided by using something like:
>> ($(RM) -f $(strip $1).log && $(strip $2) > >($(TEE) -a $(strip
>> $1).log) 2> >($(TEE) -a $(strip $1).log >&2) || \
>> ...
>>
>> This also leads to no truncated files, but the relative order of
>> stdout/stderr might be wrong.
>>
>> If the third problem should be solved too, the only solution I've
>> found was to redierect via > $(strip $1).log 2>&1 to the file and
>> then later use 'cat' to write the output to stdout (losing the
>> distinction between stdout and stderr).
>>
>> Best regards,
>> Ralf
>
More information about the build-dev
mailing list