Skip to content

Commit dc99ffe

Browse files
committed
Pprof server waits for required interface rename
The interfaces within the endpointVM get renamed to their network roles and an entry is added to /etc/hosts so that it's easy for services to bind to specific network roles irrespective of actual network configuration. As components do not launch until the network is fully configured and initialized this works as expected, but fails for the pprof server embedded in vic-init that is performing the network initialization. This adds logic to block the pprof initialization until the expected name (client.localhost) resolves. This only impacts execution with debug level of >=2.
1 parent f2c792f commit dc99ffe

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

lib/pprof/pprof.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"net"
2323
"net/http"
24+
"time"
2425
// imported for the side effect
2526
_ "net/http/pprof"
2627
"net/url"
@@ -61,7 +62,13 @@ func init() {
6162
debugLevel = vchConfig.ExecutorConfig.Diagnostics.DebugLevel
6263
}
6364

65+
// GetPprofEndpoint determines on which interface the pprof server should be launched. This makes
66+
// an explicit assumption that there will be a `client.localhost` name when running in debug modes.
6467
func GetPprofEndpoint(component PprofPort) *url.URL {
68+
return getEndpoint(component, debugLevel)
69+
}
70+
71+
func getEndpoint(component PprofPort, debug int) *url.URL {
6572
if component >= maxPort {
6673
return nil
6774
}
@@ -70,12 +77,18 @@ func GetPprofEndpoint(component PprofPort) *url.URL {
7077
ip := "127.0.0.1"
7178
// exposing this data on an external port definitely counts as a change of behaviour,
7279
// so this is > 1, just debug on/off.
73-
if debugLevel > 1 {
74-
ips, err := net.LookupIP("client.localhost")
75-
if err != nil || len(ips) == 0 {
76-
log.Warnf("Unable to resolve 'client.localhost': ", err)
77-
} else {
80+
if debug > 1 {
81+
log.Debugf("Waiting for client.localhost to resolve before launching pprof")
82+
for {
83+
ips, err := net.LookupIP("client.localhost")
84+
if err != nil || len(ips) == 0 {
85+
log.Warnf("Unable to resolve 'client.localhost': ", err)
86+
time.Sleep(time.Second)
87+
continue
88+
}
89+
7890
ip = ips[0].String()
91+
break
7992
}
8093
}
8194

@@ -87,16 +100,20 @@ func GetPprofEndpoint(component PprofPort) *url.URL {
87100
}
88101

89102
func StartPprof(name string, component PprofPort) error {
90-
url := GetPprofEndpoint(component)
91-
if url == nil {
92-
err := fmt.Errorf("Unable to get pprof endpoint for %s.", name)
93-
log.Error(err.Error())
94-
return err
95-
}
96-
location := url.String()[7:] // Strip off leading "http://"
97-
98-
log.Info(fmt.Sprintf("Launching %s pprof server on %s", name, location))
99103
go func() {
104+
url := getEndpoint(component, debugLevel)
105+
if url == nil {
106+
log.Errorf("Unable to get pprof endpoint for %s, reverting to localhost.", name)
107+
url = getEndpoint(component, 0)
108+
if url == nil {
109+
log.Errorf("Unable to construct localhost pprof endpoint for %s, giving up", name)
110+
return
111+
}
112+
}
113+
114+
location := url.String()[7:] // Strip off leading "http://"
115+
116+
log.Info(fmt.Sprintf("Launching %s pprof server on %s", name, location))
100117
log.Info(http.ListenAndServe(location, nil))
101118
}()
102119

0 commit comments

Comments
 (0)