Module Name: src Committed By: rillig Date: Sat Sep 3 08:03:27 UTC 2022
Modified Files: src/usr.bin/make: job.c src/usr.bin/make/unit-tests: job-output-null.exp job-output-null.mk Log Message: make: fix handling of null bytes in the output in jobs mode The test job-output-null failed occasionally, depending on the exact timing of the child's write and make's read. To generate a diff of this commit: cvs rdiff -u -r1.453 -r1.454 src/usr.bin/make/job.c cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/job-output-null.exp \ src/usr.bin/make/unit-tests/job-output-null.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/job.c diff -u src/usr.bin/make/job.c:1.453 src/usr.bin/make/job.c:1.454 --- src/usr.bin/make/job.c:1.453 Sat May 7 08:01:20 2022 +++ src/usr.bin/make/job.c Sat Sep 3 08:03:27 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.453 2022/05/07 08:01:20 rillig Exp $ */ +/* $NetBSD: job.c,v 1.454 2022/09/03 08:03:27 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -142,7 +142,7 @@ #include "trace.h" /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: job.c,v 1.453 2022/05/07 08:01:20 rillig Exp $"); +MAKE_RCSID("$NetBSD: job.c,v 1.454 2022/09/03 08:03:27 rillig Exp $"); /* * A shell defines how the commands are run. All commands for a target are @@ -1864,18 +1864,14 @@ again: * true. */ max = job->curPos + nr; + for (i = job->curPos; i < max; i++) + if (job->outBuf[i] == '\0') + job->outBuf[i] = ' '; for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) { if (job->outBuf[i] == '\n') { gotNL = true; break; - } else if (job->outBuf[i] == '\0') { - /* - * FIXME: The null characters are only replaced with - * space _after_ the last '\n'. Everywhere else they - * hide the rest of the command output. - */ - job->outBuf[i] = ' '; } } Index: src/usr.bin/make/unit-tests/job-output-null.exp diff -u src/usr.bin/make/unit-tests/job-output-null.exp:1.3 src/usr.bin/make/unit-tests/job-output-null.exp:1.4 --- src/usr.bin/make/unit-tests/job-output-null.exp:1.3 Sun Sep 12 10:26:49 2021 +++ src/usr.bin/make/unit-tests/job-output-null.exp Sat Sep 3 08:03:27 2022 @@ -1,4 +1,6 @@ -1 -2a +1 trailing +2a trailing +2b trailing +2c trailing 3a without newline, 3b without newline. exit status 0 Index: src/usr.bin/make/unit-tests/job-output-null.mk diff -u src/usr.bin/make/unit-tests/job-output-null.mk:1.3 src/usr.bin/make/unit-tests/job-output-null.mk:1.4 --- src/usr.bin/make/unit-tests/job-output-null.mk:1.3 Sun Sep 12 10:26:49 2021 +++ src/usr.bin/make/unit-tests/job-output-null.mk Sat Sep 3 08:03:27 2022 @@ -1,11 +1,11 @@ -# $NetBSD: job-output-null.mk,v 1.3 2021/09/12 10:26:49 rillig Exp $ +# $NetBSD: job-output-null.mk,v 1.4 2022/09/03 08:03:27 rillig Exp $ # # Test how null bytes in the output of a command are handled. Make processes # them using null-terminated strings, which may cut off some of the output. # -# As of 2021-04-15, make handles null bytes from the child process -# inconsistently. It's an edge case though since typically the child -# processes output text. +# Before job.c 1.454 from 2022-09-03, make handled null bytes in the output +# from the child process inconsistently. It's an edge case though since +# typically the child processes output text. # Note: The printf commands used in this test must only use a single format # string, without parameters. This is because it is implementation-dependent @@ -16,30 +16,40 @@ # NetBSD /bin/ksh 3 x write("fmt") (via /bin/printf) # Bash 5 3 x write("fmt") # -# In the latter case the output may arrive in parts, which in this test makes -# a crucial difference since the outcome of the test depends on whether there -# is a '\n' in each of the blocks from the output. +# In the latter case the output may arrive in 1 to 3 parts, depending on the +# exact timing, which in this test makes a crucial difference since before +# job.c 1.454 from 2022-09-03, the outcome of the test depended on whether +# there was a '\n' in each of the blocks from the output. Depending on the +# exact timing, the output of that test varied, its possible values were '2a', +# '2a 2b', '2a 2c', '2a 2b 2c'. .MAKEFLAGS: -j1 # force jobs mode all: .PHONY - # The null byte from the command output is kept as-is. - # See CollectOutput, which looks like it intended to replace these - # null bytes with simple spaces. + # The null byte from the command output is replaced with a single + # space by CollectOutput. @printf '1\0trailing\n' + # expect: 1 trailing # Give the parent process a chance to see the above output, but not # yet the output from the next printf command. @sleep 1 - # All null bytes from the command output are kept as-is. + # Each null byte from the command output is replaced with a single + # space. @printf '2a\0trailing\n''2b\0trailing\n''2c\0trailing\n' + # expect: 2a trailing + # expect: 2b trailing + # expect: 2c trailing @sleep 1 - # The null bytes are replaced with spaces since they are not followed - # by a newline. + # Each null byte from the command output is replaced with a single + # space. Because there is no trailing newline in the output, these + # null bytes were replaced with spaces even before job.c 1.454 from + # 2022-09-03, unlike in the cases above. # # The three null bytes in a row test whether this output is # compressed to a single space like in DebugFailedTarget. It isn't. @printf '3a\0without\0\0\0newline, 3b\0without\0\0\0newline.' + # expect: 3a without newline, 3b without newline.