github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/pprof/socket.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package pprof
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"net/http"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  
    14  	"github.com/juju/loggo"
    15  )
    16  
    17  var logger = loggo.GetLogger("juju.cmd.pprof")
    18  
    19  // Start starts a pprof server listening on a unix socket in /tmp.
    20  // The name of the file is derived from the name of the process, as
    21  // provided by os.Args[0], and the pid of the process.
    22  // Start returns a function which will stop the pprof server and clean
    23  // up the socket file.
    24  func Start() func() error {
    25  	if runtime.GOOS != "linux" {
    26  		logger.Infof("pprof debugging not supported on %q", runtime.GOOS)
    27  		return func() error { return nil }
    28  	}
    29  
    30  	mux := http.NewServeMux()
    31  	mux.Handle("/debug/pprof/", http.HandlerFunc(Index))
    32  	mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
    33  	mux.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
    34  	mux.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
    35  
    36  	srv := http.Server{
    37  		Handler: mux,
    38  	}
    39  
    40  	path := socketpath()
    41  	addr, err := net.ResolveUnixAddr("unix", path)
    42  	if err != nil {
    43  		logger.Errorf("unable to resolve unix socket: %v", err)
    44  		return func() error { return nil }
    45  	}
    46  
    47  	// Try to remove the socket if already present.
    48  	os.Remove(path)
    49  
    50  	l, err := net.ListenUnix("unix", addr)
    51  	if err != nil {
    52  		logger.Errorf("unable to listen on unix socket: %v", err)
    53  		return func() error { return nil }
    54  	}
    55  
    56  	go func() {
    57  		defer os.Remove(path)
    58  
    59  		// Ignore the error from calling l.Close.
    60  		srv.Serve(l)
    61  	}()
    62  
    63  	return l.Close
    64  }
    65  
    66  // socketpath returns the path for this processes' pprof socket.
    67  func socketpath() string {
    68  	cmd := filepath.Base(os.Args[0])
    69  	name := fmt.Sprintf("pprof.%s.%d", cmd, os.Getpid())
    70  	path := filepath.Join(os.TempDir(), name)
    71  	return path
    72  }