fsmonitor: read entirety of watchman output

In Perl, setting $/ sets the string that is used as the "record separator," which sets the boundary that the `<>` construct reads to. Setting `local $/ = 0666;` evaluates the octal, getting 438, and stringifies it. Thus, the later read from `<CHLD_OUT>` stops as soon as it encounters the string "438" in the watchman output, yielding invalid JSON; repositories containing filenames with SHA1 hashes are able to trip this easily. Set `$/` to undefined, thus slurping all output from watchman. Also close STDIN which is provided to watchman, to better guarantee that we cannot deadlock with watchman while both attempting to read. Signed-off-by: Alex Vandiver <alexmv@dropbox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alex Vandiver committed Oct 3, 2017 at 23:27 UTC 2a387b17c5bc5e0872bed352a41a2b312ea86f9b
2 files changed +4 -8
t/t7519/fsmonitor-watchman
+2 -4
@@ -50,9 +50,6 @@ launch_watchman();
50
51 sub launch_watchman {
52
53 - # Set input record separator
54 - local $/ = 0666;
55 -
53 my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j')
54 or die "open2() failed: $!\n" .
55 "Falling back to scanning...\n";
@@ -83,7 +80,8 @@ sub launch_watchman {
80 close $fh;
81
82 print CHLD_IN $query;
86 - my $response = <CHLD_OUT>;
83 + close CHLD_IN;
84 + my $response = do {local $/; <CHLD_OUT>};
85
86 open ($fh, ">", ".git/watchman-response.json");
87 print $fh $response;
templates/hooks--fsmonitor-watchman.sample
+2 -4
@@ -49,9 +49,6 @@ launch_watchman();
49
50 sub launch_watchman {
51
52 - # Set input record separator
53 - local $/ = 0666;
54 -
52 my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j')
53 or die "open2() failed: $!\n" .
54 "Falling back to scanning...\n";
@@ -78,7 +75,8 @@ sub launch_watchman {
75 END
76
77 print CHLD_IN $query;
81 - my $response = <CHLD_OUT>;
78 + close CHLD_IN;
79 + my $response = do {local $/; <CHLD_OUT>};
80
81 die "Watchman: command returned no output.\n" .
82 "Falling back to scanning...\n" if $response eq "";