r241201 - [analyzer] Prevent ccc/c++-analyzer from hanging on Windows.
Anton Yartsev
anton.yartsev at gmail.com
Wed Jul 1 15:35:30 PDT 2015
Author: ayartsev
Date: Wed Jul 1 17:35:29 2015
New Revision: 241201
URL: http://llvm.org/viewvc/llvm-project?rev=241201&view=rev
Log:
[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.
Modified:
cfe/trunk/tools/scan-build/ccc-analyzer
cfe/trunk/tools/scan-build/scan-build
Modified: cfe/trunk/tools/scan-build/ccc-analyzer
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/ccc-analyzer?rev=241201&r1=241200&r2=241201&view=diff
==============================================================================
--- cfe/trunk/tools/scan-build/ccc-analyzer (original)
+++ cfe/trunk/tools/scan-build/ccc-analyzer Wed Jul 1 17:35:29 2015
@@ -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) {
Modified: cfe/trunk/tools/scan-build/scan-build
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/scan-build/scan-build?rev=241201&r1=241200&r2=241201&view=diff
==============================================================================
--- cfe/trunk/tools/scan-build/scan-build (original)
+++ cfe/trunk/tools/scan-build/scan-build Wed Jul 1 17:35:29 2015
@@ -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
More information about the cfe-commits
mailing list