Skip to content

Commit 30c36a9

Browse files
committed
add signal handling for build
1 parent 69bdcf8 commit 30c36a9

File tree

1 file changed

+91
-27
lines changed

1 file changed

+91
-27
lines changed

cmd/gokr-rebuild-kernel/kernel.go

Lines changed: 91 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package main
22

33
import (
4+
"context"
5+
"encoding/hex"
46
"flag"
57
"fmt"
68
"io"
7-
"io/ioutil"
89
"log"
10+
"math/rand"
911
"os"
1012
"os/exec"
13+
"os/signal"
1114
"os/user"
1215
"path/filepath"
1316
"strings"
17+
"syscall"
1418
"text/template"
19+
"time"
1520
)
1621

1722
const dockerFileContents = `
@@ -122,14 +127,28 @@ func getContainerExecutable() (string, error) {
122127
return "", fmt.Errorf("none of %v found in $PATH", choices)
123128
}
124129

130+
var fatalErr error
131+
132+
func fatal(e error) {
133+
log.Println(e)
134+
fatalErr = e
135+
}
136+
125137
func main() {
138+
defer func() {
139+
if fatalErr != nil {
140+
os.Exit(1)
141+
}
142+
}()
143+
126144
var overwriteContainerExecutable = flag.String("overwrite_container_executable",
127145
"",
128146
"E.g. docker or podman to overwrite the automatically detected container executable")
129147
flag.Parse()
130148
executable, err := getContainerExecutable()
131149
if err != nil {
132-
log.Fatal(err)
150+
fatal(err)
151+
return
133152
}
134153
if *overwriteContainerExecutable != "" {
135154
executable = *overwriteContainerExecutable
@@ -138,9 +157,10 @@ func main() {
138157
// We explicitly use /tmp, because Docker only allows volume mounts under
139158
// certain paths on certain platforms, see
140159
// e.g. https://docs.docker.com/docker-for-mac/osxfs/#namespaces for macOS.
141-
tmp, err := ioutil.TempDir("/tmp", "gokr-rebuild-kernel")
160+
tmp, err := os.MkdirTemp("/tmp", "gokr-rebuild-kernel")
142161
if err != nil {
143-
log.Fatal(err)
162+
fatal(err)
163+
return
144164
}
145165
defer os.RemoveAll(tmp)
146166

@@ -157,51 +177,61 @@ func main() {
157177
for _, filename := range patchFiles {
158178
path, err := find(filename)
159179
if err != nil {
160-
log.Fatal(err)
180+
fatal(err)
181+
return
161182
}
162183
patchPaths = append(patchPaths, path)
163184
}
164185

165186
kernelPath, err := find("vmlinuz")
166187
if err != nil {
167-
log.Fatal(err)
188+
fatal(err)
189+
return
168190
}
169191
dtbPath, err := find("bcm2710-rpi-3-b.dtb")
170192
if err != nil {
171-
log.Fatal(err)
193+
fatal(err)
194+
return
172195
}
173196
dtbPlusPath, err := find("bcm2710-rpi-3-b-plus.dtb")
174197
if err != nil {
175-
log.Fatal(err)
198+
fatal(err)
199+
return
176200
}
177201
dtbZero2WPath, err := find("bcm2710-rpi-zero-2.dtb")
178202
if err != nil {
179-
log.Fatal(err)
203+
fatal(err)
204+
return
180205
}
181206
dtbCM3Path, err := find("bcm2710-rpi-cm3.dtb")
182207
if err != nil {
183-
log.Fatal(err)
208+
fatal(err)
209+
return
184210
}
185211
dtb4Path, err := find("bcm2711-rpi-4-b.dtb")
186212
if err != nil {
187-
log.Fatal(err)
213+
fatal(err)
214+
return
188215
}
189216

190217
// Copy all files into the temporary directory so that docker
191218
// includes them in the build context.
192219
for _, path := range patchPaths {
193220
if err := copyFile(filepath.Join(tmp, filepath.Base(path)), path); err != nil {
194-
log.Fatal(err)
221+
fatal(err)
222+
return
195223
}
196224
}
197225

198226
u, err := user.Current()
199227
if err != nil {
200-
log.Fatal(err)
228+
fatal(err)
229+
return
201230
}
202231
dockerFile, err := os.Create(filepath.Join(tmp, "Dockerfile"))
203232
if err != nil {
204-
log.Fatal(err)
233+
fatal(err)
234+
return
205235
}
206236

207237
if err := dockerFileTmpl.Execute(dockerFile, struct {
@@ -215,11 +245,13 @@ func main() {
215245
BuildPath: buildPath,
216246
Patches: patchFiles,
217247
}); err != nil {
218-
log.Fatal(err)
248+
fatal(err)
249+
return
219250
}
220251

221252
if err := dockerFile.Close(); err != nil {
222-
log.Fatal(err)
253+
fatal(err)
254+
return
223255
}
224256

225257
log.Printf("building %s container for kernel compilation", execName)
@@ -233,56 +265,88 @@ func main() {
233265
dockerBuild.Stdout = os.Stdout
234266
dockerBuild.Stderr = os.Stderr
235267
if err := dockerBuild.Run(); err != nil {
236-
log.Fatalf("%s build: %v (cmd: %v)", execName, err, dockerBuild.Args)
268+
fatal(fmt.Errorf("%s build: %v (cmd: %v)", execName, err, dockerBuild.Args))
269+
return
237270
}
238271

239272
log.Printf("compiling kernel")
240273

274+
ctx, cancel := context.WithCancel(context.Background())
275+
signalChan := make(chan os.Signal, 1)
276+
go func() {
277+
<-signalChan
278+
cancel()
279+
log.Println("Stopping ...")
280+
}()
281+
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
282+
283+
rand.Seed(time.Now().UnixNano())
284+
randBytes := make([]byte, 4)
285+
rand.Read(randBytes)
286+
containerId := "compilekernel-" + hex.EncodeToString(randBytes)
287+
241288
var dockerRun *exec.Cmd
242289
if execName == "podman" {
243-
dockerRun = exec.Command(executable,
290+
dockerRun = exec.CommandContext(ctx, executable,
244291
"run",
292+
"--rm",
245293
"--userns=keep-id",
246294
"--rm",
295+
"--name", containerId,
247296
"--volume", tmp+":/tmp/buildresult:Z",
248297
"gokr-rebuild-kernel")
249298
} else {
250-
dockerRun = exec.Command(executable,
299+
dockerRun = exec.CommandContext(ctx, executable,
251300
"run",
252301
"--rm",
302+
"--name", containerId,
253303
"--volume", tmp+":/tmp/buildresult:Z",
254304
"gokr-rebuild-kernel")
255305
}
306+
defer func() {
307+
if !dockerRun.ProcessState.Success() {
308+
exec.Command(
309+
executable,
310+
"stop", containerId,
311+
).Run()
312+
}
313+
}()
256314
dockerRun.Dir = tmp
257315
dockerRun.Stdout = os.Stdout
258316
dockerRun.Stderr = os.Stderr
259317
if err := dockerRun.Run(); err != nil {
260-
log.Fatalf("%s run: %v (cmd: %v)", execName, err, dockerRun.Args)
318+
fatal(fmt.Errorf("%s run: %v (cmd: %v)", execName, err, dockerRun.Args))
319+
return
261320
}
262321

263322
if err := copyFile(kernelPath, filepath.Join(tmp, "vmlinuz")); err != nil {
264-
log.Fatal(err)
323+
fatal(err)
324+
return
265325
}
266326

267327
if err := copyFile(dtbPath, filepath.Join(tmp, "bcm2710-rpi-3-b.dtb")); err != nil {
268-
log.Fatal(err)
328+
fatal(err)
329+
return
269330
}
270331

271332
// Until the Raspberry Pi Zero 2 W DTB is built by the kernel, use bcm2710-rpi-3-b.dtb:
272333
if err := copyFile(dtbZero2WPath, filepath.Join(tmp, "bcm2710-rpi-3-b.dtb")); err != nil {
273-
log.Fatal(err)
334+
fatal(err)
335+
return
274336
}
275337

276338
if err := copyFile(dtbPlusPath, filepath.Join(tmp, "bcm2710-rpi-3-b-plus.dtb")); err != nil {
277-
log.Fatal(err)
339+
fatal(err)
340+
return
278341
}
279342

280343
if err := copyFile(dtbCM3Path, filepath.Join(tmp, "bcm2710-rpi-cm3.dtb")); err != nil {
281-
log.Fatal(err)
344+
fatal(err)
345+
return
282346
}
283347

284348
if err := copyFile(dtb4Path, filepath.Join(tmp, "bcm2711-rpi-4-b.dtb")); err != nil {
285-
log.Fatal(err)
349+
fatal(err)
350+
return
286351
}
287-
288352
}

0 commit comments

Comments
 (0)