Skip to content

Commit 1967543

Browse files
findleyrgopherbot
authored andcommitted
telemetry: fix automated crash reporting using telemetry.Start
Following CL 592017, the child process started by telemetry.Start no longer opens the counter file, causing crash reports to be dropped on the floor. Fix this, with a test. Fixes golang/go#69681 Change-Id: I423533d5b1e2369f13880cecd9137cd7c9239240 Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/616396 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Robert Findley <[email protected]>
1 parent 1b7b43a commit 1967543

File tree

2 files changed

+49
-17
lines changed

2 files changed

+49
-17
lines changed

start.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ func child(config Config) {
271271
uploadStartTime := config.UploadStartTime
272272
uploadURL := config.UploadURL
273273

274+
// The crashmonitor and/or upload process may themselves record counters.
275+
counter.Open()
276+
274277
// Start crashmonitoring and uploading depending on what's requested
275278
// and wait for the longer running child to complete before exiting:
276279
// if we collected a crash before the upload finished, wait for the

start_test.go

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"golang.org/x/telemetry/counter/countertest"
2222
"golang.org/x/telemetry/internal/configtest"
2323
ic "golang.org/x/telemetry/internal/counter"
24+
"golang.org/x/telemetry/internal/crashmonitor"
2425
"golang.org/x/telemetry/internal/regtest"
2526
it "golang.org/x/telemetry/internal/telemetry"
2627
"golang.org/x/telemetry/internal/testenv"
@@ -48,7 +49,6 @@ func TestMain(m *testing.M) {
4849
// runProg runs the given program.
4950
// See the switch statement below.
5051
func runProg(prog string) int {
51-
5252
mustGetEnv := func(envvar string) string {
5353
v := os.Getenv(envvar)
5454
if v == "" {
@@ -65,56 +65,80 @@ func runProg(prog string) int {
6565

6666
// Set global state.
6767
ic.CounterTime = func() time.Time { return asof } // must be done before Open
68-
countertest.Open(mustGetEnv(telemetryDirEnv))
68+
69+
telemetryDir := mustGetEnv(telemetryDirEnv)
6970

7071
switch prog {
7172
case "setmode":
73+
countertest.Open(telemetryDir)
7274
// Use the modified time above for the asof time.
7375
if err := it.Default.SetModeAsOf("on", asof); err != nil {
7476
log.Fatalf("setting mode: %v", err)
7577
}
7678
case "inc":
79+
countertest.Open(telemetryDir)
7780
// (CounterTime is already set above)
7881
counter.Inc("teststart/counter")
7982

80-
case "start":
83+
case "crash":
84+
telemetry.Start(telemetry.Config{
85+
// Do not call Open, to assert that Start does it (golang/go#69681).
86+
TelemetryDir: telemetryDir,
87+
ReportCrashes: true,
88+
})
89+
// Note: don't await the result of start: the child process won't complete
90+
// until the crash occurs.
91+
panic("crash!")
92+
93+
case "upload":
8194
res := telemetry.Start(telemetry.Config{
82-
// No need to set TelemetryDir since the Default dir is already set by countertest.Open.
95+
TelemetryDir: telemetryDir,
8396
Upload: true,
8497
UploadURL: mustGetEnv(uploadURLEnv),
8598
UploadStartTime: asof,
8699
})
87100
res.Wait()
101+
88102
default:
89103
log.Fatalf("unknown program %q", prog)
90104
}
91105
return 0
92106
}
93107

94-
func execProg(t *testing.T, telemetryDir, prog string, asof time.Time, env ...string) {
108+
func execProg(t *testing.T, telemetryDir, prog string, asof time.Time, expectFailure bool, env ...string) {
95109
// Run the runStart function below, via a fork+exec trick.
96110
exe, err := os.Executable()
97111
if err != nil {
98112
t.Error(err)
99113
return
100114
}
101115
cmd := exec.Command(exe, "** TestStart **") // this unused arg is just for ps(1)
102-
cmd.Stderr = os.Stderr
116+
if !expectFailure {
117+
cmd.Stderr = os.Stderr
118+
}
103119
cmd.Env = os.Environ()
104120
cmd.Env = append(cmd.Env, asofEnv+"="+asof.Format(it.DateOnly))
105121
cmd.Env = append(cmd.Env, telemetryDirEnv+"="+telemetryDir)
106122
cmd.Env = append(cmd.Env, runStartEnv+"="+prog) // see TestMain
107123
cmd.Env = append(cmd.Env, env...)
108124
out, err := cmd.Output()
109-
if err != nil {
110-
t.Errorf("program failed unexpectedly (%v)\n%s", err, out)
125+
if expectFailure {
126+
if err == nil {
127+
t.Errorf("program succeeded unexpectedly:\n%s", out)
128+
}
129+
} else if err != nil {
130+
t.Errorf("program failed unexpectedly (%v):\n%s", err, out)
111131
}
112132
}
113133

114134
func TestStart(t *testing.T) {
115135
testenv.SkipIfUnsupportedPlatform(t)
116136
testenv.MustHaveExec(t)
117137

138+
if !crashmonitor.Supported() {
139+
t.Skip("crashmonitor not supported")
140+
}
141+
118142
// This test sets up a telemetry environment, and then runs a test program
119143
// that increments a counter, and uploads via telemetry.Start.
120144

@@ -127,21 +151,26 @@ func TestStart(t *testing.T) {
127151
if err != nil {
128152
t.Errorf("error reading body: %v", err)
129153
} else {
130-
if body := string(body); !strings.Contains(body, "teststart/counter") {
154+
body := string(body)
155+
if !strings.Contains(body, "teststart/counter") {
131156
t.Errorf("upload does not contain \"teststart/counter\":\n%s", body)
132157
}
158+
if !strings.Contains(body, "crash/crash") {
159+
t.Errorf("upload does not contain \"crash/crash\":\n%s", body)
160+
}
133161
}
134162
}))
135163
uploadEnv := []string{uploadURLEnv + "=" + server.URL}
136164

137-
uc := regtest.CreateTestUploadConfig(t, []string{"teststart/counter"}, nil)
165+
uc := regtest.CreateTestUploadConfig(t, []string{"teststart/counter"}, []string{"crash/crash"})
138166
uploadEnv = append(uploadEnv, configtest.LocalProxyEnv(t, uc, "v1.2.3")...)
139167

140168
// Script programs.
141169
now := time.Now()
142-
execProg(t, telemetryDir, "setmode", now.Add(-30*24*time.Hour)) // back-date telemetry acceptance
143-
execProg(t, telemetryDir, "inc", now.Add(-8*24*time.Hour)) // increment the counter
144-
execProg(t, telemetryDir, "start", now, uploadEnv...) // run start
170+
execProg(t, telemetryDir, "setmode", now.Add(-30*24*time.Hour), false) // back-date telemetry acceptance
171+
execProg(t, telemetryDir, "inc", now.Add(-8*24*time.Hour), false) // increment the counter
172+
execProg(t, telemetryDir, "crash", now.Add(-8*24*time.Hour), true) // run start
173+
execProg(t, telemetryDir, "upload", now, false, uploadEnv...) // run start
145174

146175
if !uploaded {
147176
t.Fatalf("no upload occurred on %v", os.Getpid())
@@ -171,12 +200,12 @@ func TestConcurrentStart(t *testing.T) {
171200
uploadEnv = append(uploadEnv, configtest.LocalProxyEnv(t, uc, "v1.2.3")...)
172201

173202
now := time.Now()
174-
execProg(t, telemetryDir, "setmode", now.Add(-365*24*time.Hour)) // back-date telemetry acceptance
175-
execProg(t, telemetryDir, "inc", now.Add(-8*24*time.Hour)) // increment the counter
203+
execProg(t, telemetryDir, "setmode", now.Add(-365*24*time.Hour), false) // back-date telemetry acceptance
204+
execProg(t, telemetryDir, "inc", now.Add(-8*24*time.Hour), false) // increment the counter
176205

177206
// Populate three weeks of counters to upload.
178207
for i := -28; i < -7; i++ { // Populate three weeks of counters to upload.
179-
execProg(t, telemetryDir, "inc", now.Add(time.Duration(i)*24*time.Hour))
208+
execProg(t, telemetryDir, "inc", now.Add(time.Duration(i)*24*time.Hour), false)
180209
}
181210

182211
// Run start concurrently.
@@ -185,7 +214,7 @@ func TestConcurrentStart(t *testing.T) {
185214
wg.Add(1)
186215
go func() {
187216
defer wg.Done()
188-
execProg(t, telemetryDir, "start", now, uploadEnv...)
217+
execProg(t, telemetryDir, "upload", now, false, uploadEnv...)
189218
}()
190219
}
191220
wg.Wait()

0 commit comments

Comments
 (0)