From: Shivakumar GN Date: Tue, 27 Aug 2013 17:35:06 +0000 (-0700) Subject: misc/pprof: pprof http used with net/http/pprof not working on windows/amd64 X-Git-Tag: go1.2rc2~415 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=daed1fee8b8fb7e899fa137e5df62df01bd1c18d;p=gostls13.git misc/pprof: pprof http used with net/http/pprof not working on windows/amd64 Removed posix assumptions in temporary file generation Removed curl dependence Changed opening of svg file These must now work including symbol resolution. [1] go tool pprof http://.../debug/pprof/profile [2] go tool pprof http://.../debug/pprof/profile Fixes 6177. R=golang-dev, alex.brainman, bradfitz, kamil.kisiel CC=golang-dev https://golang.org/cl/13085043 --- diff --git a/misc/pprof b/misc/pprof index 7c3272b5e0..35749483fd 100755 --- a/misc/pprof +++ b/misc/pprof @@ -79,6 +79,8 @@ use strict; use warnings; use Getopt::Long; use File::Temp; +use LWP::UserAgent; +use File::Copy; my $PPROF_VERSION = "1.5"; @@ -104,7 +106,6 @@ my $GV = "gv"; my $KCACHEGRIND = "kcachegrind"; my $PS2PDF = "ps2pdf"; # These are used for dynamic profiles -my $CURL = "curl"; # These are the web pages that servers need to support for dynamic profiles my $HEAP_PAGE = "/pprof/heap"; @@ -138,8 +139,8 @@ my $sep_address = undef; my $OS = $^O; my $DEVNULL = "/dev/null"; if ($^O =~ /MSWin32|cygwin|msys/) { - $OS = "windows"; - $DEVNULL = "NUL"; + $OS = "windows"; + $DEVNULL = "NUL"; } ##### Argument parsing ##### @@ -2977,10 +2978,13 @@ sub IsSymbolizedProfileFile { sub CheckSymbolPage { my $url = SymbolPageURL(); print STDERR "Read $url\n"; - open(SYMBOL, "$CURL -s '$url' |"); - my $line = ; + + my $ua = LWP::UserAgent->new; + my $response = $ua->get($url); + error("Failed to get symbol page from $url\n") unless $response->is_success; + + my $line = $response->content; $line =~ s/\r//g; # turn windows-looking lines into unix-looking lines - close(SYMBOL); unless (defined($line)) { error("$url doesn't exist\n"); } @@ -3022,35 +3026,20 @@ sub SymbolPageURL { sub FetchProgramName() { my ($scheme, $host, $port, $prefix, $path) = ParseProfileURL($main::pfile_args[0]); my $url = "$scheme://$host:$port$prefix$PROGRAM_NAME_PAGE"; - my $command_line = "$CURL -s '$url'"; - open(CMDLINE, "$command_line |") or error($command_line); - my $cmdline = ; + + my $ua = LWP::UserAgent->new; + my $response = $ua->get($url); + error("Failed to get program name from $url\n") unless $response->is_success; + my $cmdline = $response->content; + + $cmdline =~ s/\n.*//s; $cmdline =~ s/\r//g; # turn windows-looking lines into unix-looking lines - close(CMDLINE); error("Failed to get program name from $url\n") unless defined($cmdline); $cmdline =~ s/\x00.+//; # Remove argv[1] and latters. $cmdline =~ s!\n!!g; # Remove LFs. return $cmdline; } -# Gee, curl's -L (--location) option isn't reliable at least -# with its 7.12.3 version. Curl will forget to post data if -# there is a redirection. This function is a workaround for -# curl. Redirection happens on borg hosts. -sub ResolveRedirectionForCurl { - my $url = shift; - my $command_line = "$CURL -s --head '$url'"; - open(CMDLINE, "$command_line |") or error($command_line); - while () { - s/\r//g; # turn windows-looking lines into unix-looking lines - if (/^Location: (.*)/) { - $url = $1; - } - } - close(CMDLINE); - return $url; -} - # Reads a symbol map from the file handle name given as $1, returning # the resulting symbol map. Also processes variables relating to symbols. # Currently, the only variable processed is 'binary=' which updates @@ -3107,9 +3096,17 @@ sub FetchSymbols { close(POSTFILE); my $url = SymbolPageURL(); - $url = ResolveRedirectionForCurl($url); - my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'"; - open(SYMBOL, "$command_line |") or error($command_line); + my $req = HTTP::Request->new(POST => $url); + $req->content($post_data); + my $lwp = LWP::UserAgent->new; + my $response = $lwp->request($req); + + my $tmp_symbol = File::Temp->new()->filename; + open(SYMBOL, ">$tmp_symbol"); + print SYMBOL $response->content; + close(SYMBOL); + + open(SYMBOL, "<$tmp_symbol") || error("$tmp_symbol"); ReadSymbols(*SYMBOL{IO}, $symbol_map); close(SYMBOL); } @@ -3175,7 +3172,7 @@ sub FetchDynamicProfile { my $profile_file = MakeProfileBaseName($binary_name, $profile_name); my $url; - my $curl_timeout; + my $timeout; if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)) { if ($path =~ m/$PROFILE_PAGE/) { $url = sprintf("$scheme://$host:$port$prefix$path?seconds=%d", @@ -3189,7 +3186,7 @@ sub FetchDynamicProfile { $url = sprintf("$scheme://$profile_name" . "seconds=%d", $main::opt_seconds); } - $curl_timeout = sprintf("--max-time %d", + $timeout = sprintf("%d", int($main::opt_seconds * 1.01 + 60)); } else { # For non-CPU profiles, we add a type-extension to @@ -3198,22 +3195,16 @@ sub FetchDynamicProfile { $suffix =~ s,/,.,g; $profile_file .= "$suffix"; $url = "$scheme://$host:$port$prefix$path"; - $curl_timeout = ""; + $timeout = ""; } - my $profile_dir = $ENV{"PPROF_TMPDIR"} || ($ENV{HOME} . "/pprof"); - if (!(-d $profile_dir)) { - mkdir($profile_dir) - || die("Unable to create profile directory $profile_dir: $!\n"); - } - my $tmp_profile = "$profile_dir/.tmp.$profile_file"; - my $real_profile = "$profile_dir/$profile_file"; + my $tmp_profile = File::Temp->new()->filename; + my $real_profile = File::Temp->new()->filename; if ($fetch_name_only > 0) { return $real_profile; } - my $cmd = "$CURL $curl_timeout -s -o $tmp_profile '$url'"; if (($path =~ m/$PROFILE_PAGE/) || ($path =~ m/$PMUPROFILE_PAGE/)){ print STDERR "Gathering CPU profile from $url for $main::opt_seconds seconds to\n ${real_profile}\n"; if ($encourage_patience) { @@ -3223,12 +3214,21 @@ sub FetchDynamicProfile { print STDERR "Fetching $path profile from $host:$port to\n ${real_profile}\n"; } - (system($cmd) == 0) || error("Failed to get profile: $cmd: $!\n"); - open(TMPPROF, "$tmp_profile") || error("Cannot open $tmp_profile: $!\n"); - my $line = ; - close(TMPPROF); + my $ua = LWP::UserAgent->new; + $ua->timeout($timeout); + my $response = $ua->get($url); + + error("Failed to get profile: $url $timeout!\n") unless $response->is_success; + + open(OUTFILE, ">$tmp_profile"); + binmode(OUTFILE); + print OUTFILE $response->content; + close(OUTFILE); + + my $line = $response->content; $line !~ /^Could not enable CPU profiling/ || error($line); - (system("mv $tmp_profile $real_profile") == 0) || error("Unable to rename profile\n"); + + copy($tmp_profile, $real_profile) || error("Unable to copy profile\n"); print STDERR "Wrote profile to $real_profile\n"; $main::collected_profile = $real_profile; return $main::collected_profile; @@ -4683,6 +4683,9 @@ sub ConfigureTool { sub cleanup { unlink($main::tmpfile_sym); unlink(keys %main::tempnames); + if (defined($main::collected_profile)) { + unlink($main::collected_profile); + } # We leave any collected profiles in $HOME/pprof in case the user wants # to look at them later. We print a message informing them of this.