[internal-branch.go1.23-vendor] telemetry: do not crash parent if child could not be started

Instead of calling log.Fatal if the child could not be started, call
log.Print. Various factors in the user's environment could cause the
child to not be able to start, but that shouldn't crash the parent
process (usually the go command).

Change other fatals into prints with early returns when attempting to
start the child.

Reset the crash output file to clean up if the child process could not
be started and crashmonitoring is enabled.

Updates golang/go#68976
Updates golang/go#68995

Change-Id: I42f55dc90f68f91b272a7ebf64d2a4a3b00815c7
Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/607595
Commit-Queue: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit 61baa7d367c9761aaa54ff14aaac79f8407d4782)
Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/609136
diff --git a/internal/crashmonitor/monitor.go b/internal/crashmonitor/monitor.go
index f475f7e..612f756 100644
--- a/internal/crashmonitor/monitor.go
+++ b/internal/crashmonitor/monitor.go
@@ -21,12 +21,12 @@
 	"golang.org/x/telemetry/internal/counter"
 )
 
-// Supported reports whether the runtime supports [runtime.SetCrashOutput].
+// Supported reports whether the runtime supports [runtime/debug.SetCrashOutput].
 //
 // TODO(adonovan): eliminate once go1.23+ is assured.
 func Supported() bool { return setCrashOutput != nil }
 
-var setCrashOutput func(*os.File) error // = runtime.SetCrashOutput on go1.23+
+var setCrashOutput func(*os.File) error // = runtime/debug.SetCrashOutput on go1.23+
 
 // Parent sets up the parent side of the crashmonitor. It requires
 // exclusive use of a writable pipe connected to the child process's stdin.
diff --git a/start.go b/start.go
index 4b37a5c..69ebcc7 100644
--- a/start.go
+++ b/start.go
@@ -206,7 +206,8 @@
 	fd, err := os.Stat(telemetry.Default.DebugDir())
 	if err != nil {
 		if !os.IsNotExist(err) {
-			log.Fatalf("failed to stat debug directory: %v", err)
+			log.Printf("failed to stat debug directory: %v", err)
+			return
 		}
 	} else if fd.IsDir() {
 		// local/debug exists and is a directory. Set stderr to a log file path
@@ -214,23 +215,31 @@
 		childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log")
 		childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
 		if err != nil {
-			log.Fatalf("opening sidecar log file for child: %v", err)
+			log.Printf("opening sidecar log file for child: %v", err)
+			return
 		}
 		defer childLog.Close()
 		cmd.Stderr = childLog
 	}
 
+	var crashOutputFile *os.File
 	if reportCrashes {
 		pipe, err := cmd.StdinPipe()
 		if err != nil {
-			log.Fatalf("StdinPipe: %v", err)
+			log.Printf("StdinPipe: %v", err)
+			return
 		}
 
-		crashmonitor.Parent(pipe.(*os.File)) // (this conversion is safe)
+		crashOutputFile = pipe.(*os.File) // (this conversion is safe)
 	}
 
 	if err := cmd.Start(); err != nil {
-		log.Fatalf("can't start telemetry child process: %v", err)
+		// The child couldn't be started. Log the failure.
+		log.Printf("can't start telemetry child process: %v", err)
+		return
+	}
+	if reportCrashes {
+		crashmonitor.Parent(crashOutputFile)
 	}
 	result.wg.Add(1)
 	go func() {