diff options
| author | Anton Yartsev <anton.yartsev@gmail.com> | 2015-07-01 22:35:29 +0000 |
|---|---|---|
| committer | Anton Yartsev <anton.yartsev@gmail.com> | 2015-07-01 22:35:29 +0000 |
| commit | 84f9042fae76b7370b7f8a754ab6258093e5ef22 (patch) | |
| tree | 4e85d4b5bb3b1526bbe381c276ea92bc91e6440e | |
| parent | e21e0f1620bfa4a021c0802e4e8b56a494c7d35a (diff) | |
| download | bcm5719-llvm-84f9042fae76b7370b7f8a754ab6258093e5ef22.tar.gz bcm5719-llvm-84f9042fae76b7370b7f8a754ab6258093e5ef22.zip | |
[analyzer] Prevent ccc/c++-analyzer from hanging on Windows.
'fork'+'exec' combination made scan-build and ccc-analyzer hang under Windows. The patch replaces 'fork'+'exec' with more reliable 'system' (ccc-analyzer) and piped 'open' (scan-build). See http://reviews.llvm.org/D8774 and http://reviews.llvm.org/D9357 for more details.
llvm-svn: 241201
| -rwxr-xr-x | clang/tools/scan-build/ccc-analyzer | 75 | ||||
| -rwxr-xr-x | clang/tools/scan-build/scan-build | 35 |
2 files changed, 48 insertions, 62 deletions
diff --git a/clang/tools/scan-build/ccc-analyzer b/clang/tools/scan-build/ccc-analyzer index ffe6859672c..14591aef57c 100755 --- a/clang/tools/scan-build/ccc-analyzer +++ b/clang/tools/scan-build/ccc-analyzer @@ -22,6 +22,33 @@ use File::Basename; use Text::ParseWords; ##===----------------------------------------------------------------------===## +# List form 'system' with STDOUT and STDERR captured. +##===----------------------------------------------------------------------===## + +sub silent_system { + my $HtmlDir = shift; + my $Command = shift; + + # Save STDOUT and STDERR and redirect to a temporary file. + open OLDOUT, ">&", \*STDOUT; + open OLDERR, ">&", \*STDERR; + my ($TmpFH, $TmpFile) = tempfile("temp_buf_XXXXXX", + DIR => $HtmlDir, + UNLINK => 1); + open(STDOUT, ">$TmpFile"); + open(STDERR, ">&", \*STDOUT); + + # Invoke 'system', STDOUT and STDERR are output to a temporary file. + system $Command, @_; + + # Restore STDOUT and STDERR. + open STDOUT, ">&", \*OLDOUT; + open STDERR, ">&", \*OLDERR; + + return $TmpFH; +} + +##===----------------------------------------------------------------------===## # Compiler command setup. ##===----------------------------------------------------------------------===## @@ -145,7 +172,7 @@ sub ProcessClangFailure { print OUT "@$Args\n"; close OUT; `uname -a >> $PPFile.info.txt 2>&1`; - `$Compiler -v >> $PPFile.info.txt 2>&1`; + `"$Compiler" -v >> $PPFile.info.txt 2>&1`; rename($ofile, "$PPFile.stderr.txt"); return (basename $PPFile); } @@ -155,27 +182,15 @@ sub ProcessClangFailure { ##----------------------------------------------------------------------------## sub GetCCArgs { + my $HtmlDir = shift; my $mode = shift; my $Args = shift; - - pipe (FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Clang, "-###", $mode, @$Args; - } - close(TO_PARENT); my $line; - while (<FROM_CHILD>) { + my $OutputStream = silent_system($HtmlDir, $Clang, "-###", $mode, @$Args); + while (<$OutputStream>) { next if (!/\s"?-cc1"?\s/); $line = $_; } - - waitpid($pid,0); - close(FROM_CHILD); - die "could not find clang line\n" if (!defined $line); # Strip leading and trailing whitespace characters. $line =~ s/^\s+|\s+$//g; @@ -207,7 +222,7 @@ sub Analyze { $Cmd = $Clang; # Create arguments for doing regular parsing. - my $SyntaxArgs = GetCCArgs("-fsyntax-only", \@Args); + my $SyntaxArgs = GetCCArgs($HtmlDir, "-fsyntax-only", \@Args); @CmdArgsSansAnalyses = @$SyntaxArgs; # Create arguments for doing static analysis. @@ -230,7 +245,7 @@ sub Analyze { push @Args, "-Xclang", "-analyzer-viz-egraph-ubigraph"; } - my $AnalysisArgs = GetCCArgs("--analyze", \@Args); + my $AnalysisArgs = GetCCArgs($HtmlDir, "--analyze", \@Args); @CmdArgs = @$AnalysisArgs; } @@ -255,31 +270,19 @@ sub Analyze { print STDERR "#SHELL (cd '$dir' && @PrintArgs)\n"; } - # Capture the STDERR of clang and send it to a temporary file. - # Capture the STDOUT of clang and reroute it to ccc-analyzer's STDERR. + # Save STDOUT and STDERR of clang to a temporary file and reroute + # all clang output to ccc-analyzer's STDERR. # We save the output file in the 'crashes' directory if clang encounters # any problems with the file. - pipe (FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Cmd, @CmdArgs; - } - - close TO_PARENT; my ($ofh, $ofile) = tempfile("clang_output_XXXXXX", DIR => $HtmlDir); - - while (<FROM_CHILD>) { + + my $OutputStream = silent_system($HtmlDir, $Cmd, @CmdArgs); + while ( <$OutputStream> ) { print $ofh $_; print STDERR $_; } - close $ofh; - - waitpid($pid,0); - close(FROM_CHILD); my $Result = $?; + close $ofh; # Did the command die because of a signal? if ($ReportFailures) { diff --git a/clang/tools/scan-build/scan-build b/clang/tools/scan-build/scan-build index ac8e22e8cc7..d7cadc3e59e 100755 --- a/clang/tools/scan-build/scan-build +++ b/clang/tools/scan-build/scan-build @@ -1232,16 +1232,9 @@ ENDTEXT } my %EnabledCheckers; foreach my $lang ("c", "objective-c", "objective-c++", "c++") { - pipe(FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###'); - } - close(TO_PARENT); - while(<FROM_CHILD>) { + my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|"); + open(PS, $ExecLine); + while (<PS>) { foreach my $val (split /\s+/) { $val =~ s/\"//g; if ($val =~ /-analyzer-checker\=([^\s]+)/) { @@ -1249,23 +1242,14 @@ ENDTEXT } } } - waitpid($pid,0); - close(FROM_CHILD); } # Query clang for complete list of checkers. if (defined $Clang && -x $Clang) { - pipe(FROM_CHILD, TO_PARENT); - my $pid = fork(); - if ($pid == 0) { - close FROM_CHILD; - open(STDOUT,">&", \*TO_PARENT); - open(STDERR,">&", \*TO_PARENT); - exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help'); - } - close(TO_PARENT); + my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginsToLoad, "-analyzer-checker-help", "2>&1", "|"); + open(PS, $ExecLine); my $foundCheckers = 0; - while(<FROM_CHILD>) { + while (<PS>) { if (/CHECKERS:/) { $foundCheckers = 1; last; @@ -1277,7 +1261,7 @@ ENDTEXT else { print("\nAVAILABLE CHECKERS:\n\n"); my $skip = 0; - while(<FROM_CHILD>) { + while(<PS>) { if (/experimental/) { $skip = 1; next; @@ -1314,10 +1298,9 @@ ENDTEXT } print $_; } - print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n" + print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n"; } - waitpid($pid,0); - close(FROM_CHILD); + close PS; } print <<ENDTEXT |

