11package main
22
33import (
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
1722const 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+
125137func 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