@@ -74,13 +74,13 @@ func main() {
7474 logger .InitBestEffort (logFlags )
7575
7676 rpmsDirAbsPath , err := filepath .Abs (* rpmsDirPath )
77- logger .PanicOnError (err , "Unable to find absolute path for RPMs directory '%s'" , * rpmsDirPath )
77+ logger .FatalOnError (err , "Unable to find absolute path for RPMs directory '%s'" , * rpmsDirPath )
7878
7979 toolchainDirAbsPath , err := filepath .Abs (* toolchainDirPath )
80- logger .PanicOnError (err , "Unable to find absolute path for toolchain RPMs directory '%s'" , * toolchainDirPath )
80+ logger .FatalOnError (err , "Unable to find absolute path for toolchain RPMs directory '%s'" , * toolchainDirPath )
8181
8282 srpmsDirAbsPath , err := filepath .Abs (* srpmsDirPath )
83- logger .PanicOnError (err , "Unable to find absolute path for SRPMs directory '%s'" , * srpmsDirPath )
83+ logger .FatalOnError (err , "Unable to find absolute path for SRPMs directory '%s'" , * srpmsDirPath )
8484
8585 chrootDir := buildChrootDirPath (* workDir , * srpmFile , * runCheck )
8686
@@ -118,15 +118,15 @@ func main() {
118118 }
119119
120120 builtRPMs , err := buildSRPMInChroot (chrootDir , rpmsDirAbsPath , toolchainDirAbsPath , * workerTar , * srpmFile , * repoFile , * rpmmacrosFile , * outArch , defines , * noCleanup , * runCheck , * packagesToInstall , ccacheManager , * timeout )
121- logger .PanicOnError (err , "Failed to build SRPM '%s'. For details see log file: %s ." , * srpmFile , * logFlags .LogFile )
121+ logger .FatalOnError (err , "Failed to build SRPM '%s'. For details see log file: %s ." , * srpmFile , * logFlags .LogFile )
122122
123123 // For regular (non-test) package builds:
124124 // - Copy the SRPM which produced the package to the output directory.
125125 // - Write a comma-separated list of RPMs built to stdout that can be parsed by the invoker.
126126 // Any output from logger will be on stderr so stdout will only contain this output.
127127 if ! * runCheck {
128128 err = copySRPMToOutput (* srpmFile , srpmsDirAbsPath )
129- logger .PanicOnError (err , "Failed to copy SRPM '%s' to output directory '%s'." , * srpmFile , rpmsDirAbsPath )
129+ logger .FatalOnError (err , "Failed to copy SRPM '%s' to output directory '%s'." , * srpmFile , rpmsDirAbsPath )
130130
131131 fmt .Print (strings .Join (builtRPMs , "," ))
132132 }
@@ -171,6 +171,7 @@ func buildSRPMInChroot(chrootDir, rpmDirPath, toolchainDirPath, workerTar, srpmF
171171 quit := make (chan bool )
172172 go func () {
173173 logger .Log .Infof ("Building (%s)." , srpmBaseName )
174+ startTime := time .Now ()
174175
175176 for {
176177 select {
@@ -180,7 +181,7 @@ func buildSRPMInChroot(chrootDir, rpmDirPath, toolchainDirPath, workerTar, srpmF
180181 }
181182 return
182183 case <- time .After (buildHeartbeatTimeout ):
183- logger .Log .Infof ("Heartbeat: still building (%s)." , srpmBaseName )
184+ logger .Log .Infof ("Heartbeat: still building (%s) after %s ." , srpmBaseName , time . Since ( startTime ). String () )
184185 }
185186 }
186187 }()
@@ -214,34 +215,48 @@ func buildSRPMInChroot(chrootDir, rpmDirPath, toolchainDirPath, workerTar, srpmF
214215
215216 err = chroot .Initialize (workerTar , extraDirs , mountPoints , true )
216217 if err != nil {
218+ err = fmt .Errorf ("failed to initialize chroot:\n %w" , err )
217219 return
218220 }
219221 defer chroot .Close (noCleanup )
220222
221223 // Place extra files that will be needed to build into the chroot
222224 srpmFileInChroot , err := copyFilesIntoChroot (chroot , srpmFile , repoFile , rpmmacrosFile , runCheck )
223225 if err != nil {
226+ err = fmt .Errorf ("failed to copy files into chroot:\n %w" , err )
224227 return
225228 }
226229
227- // Run the build in a go routine so we can monitor and kill it if it takes too long.
230+ // Run the build in a goroutine so we can monitor and kill it if it takes too long.
231+ //
232+ // It is important to run the timeout logic inside the chroot so that the chroot cleanup
233+ // flow in chroot.Run() is executed if the build times out.
234+ //
235+ // If the timeout logic is run outside of the chroot.Run() call, the process will still
236+ // be running in the chroot's context and the automatic chroot cleanup triggered by the
237+ // process exiting will fail (see safechroot.go:cleanupAllChroots()). For example,
238+ // `unmount /path/to/chroot/dev` will fail since our root is currently `/path/to/chroot`,
239+ // and `/path/to/chroot/path/to/chroot/dev` is not a real path.
228240 results := make (chan error )
229- go func () {
230- buildErr := chroot .Run (func () (err error ) {
231- return buildRPMFromSRPMInChroot (srpmFileInChroot , outArch , runCheck , defines , packagesToInstall , isCCacheEnabled (ccacheManager ))
232- })
233- results <- buildErr
234- }()
235-
236- select {
237- case err = <- results :
238- case <- time .After (timeout ):
239- logger .Log .Errorf ("Timeout after %v: killing all processes in chroot..." , timeout )
240- shell .PermanentlyStopAllChildProcesses (unix .SIGKILL )
241- err = fmt .Errorf ("build timed out after %s" , timeout )
242- }
241+ err = chroot .Run (func () (err error ) {
242+ go func () {
243+ results <- buildRPMFromSRPMInChroot (srpmFileInChroot , outArch , runCheck , defines , packagesToInstall , isCCacheEnabled (ccacheManager ))
244+ }()
245+
246+ var chrootErr error = nil
247+ select {
248+ case chrootErr = <- results :
249+ logger .Log .Debug ("Build thread in chroot finished." )
250+ case <- time .After (timeout ):
251+ logger .Log .Errorf ("Timeout after %v: stopping chroot..." , timeout )
252+ shell .StopAllChildProcesses (unix .SIGKILL )
253+ chrootErr = fmt .Errorf ("build timed out after %s" , timeout )
254+ }
255+ return chrootErr // Internal error is returned via the channel
256+ })
243257
244258 if err != nil {
259+ err = fmt .Errorf ("failed to build RPM from SRPM in chroot:\n %w" , err )
245260 return
246261 }
247262
@@ -266,18 +281,21 @@ func buildRPMFromSRPMInChroot(srpmFile, outArch string, runCheck bool, defines m
266281 // Convert /localrpms into a repository that a package manager can use.
267282 err = rpmrepomanager .CreateRepo (chrootLocalRpmsDir )
268283 if err != nil {
284+ err = fmt .Errorf ("failed to create local RPM repository:\n %w" , err )
269285 return
270286 }
271287
272288 // Convert /toolchainrpms into a repository that a package manager can use.
273289 err = rpmrepomanager .CreateRepo (chrootLocalToolchainDir )
274290 if err != nil {
291+ err = fmt .Errorf ("failed to create toolchain RPM repository:\n %w" , err )
275292 return
276293 }
277294
278295 // install any additional packages, such as build dependencies.
279296 err = tdnfInstall (packagesToInstall )
280297 if err != nil {
298+ err = fmt .Errorf ("failed to install additional packages:\n %w" , err )
281299 return
282300 }
283301
@@ -286,6 +304,7 @@ func buildRPMFromSRPMInChroot(srpmFile, outArch string, runCheck bool, defines m
286304 logger .Log .Infof ("USE_CCACHE: installing package: %s" , ccachePkgName [0 ])
287305 err = tdnfInstall (ccachePkgName )
288306 if err != nil {
307+ err = fmt .Errorf ("failed to install ccache:\n %w" , err )
289308 return
290309 }
291310 }
@@ -296,6 +315,7 @@ func buildRPMFromSRPMInChroot(srpmFile, outArch string, runCheck bool, defines m
296315 // build failures.
297316 err = removeLibArchivesFromSystem ()
298317 if err != nil {
318+ err = fmt .Errorf ("failed to remove lib archives from system:\n %w" , err )
299319 return
300320 }
301321
@@ -305,6 +325,10 @@ func buildRPMFromSRPMInChroot(srpmFile, outArch string, runCheck bool, defines m
305325 } else {
306326 err = rpm .BuildRPMFromSRPM (srpmFile , outArch , defines )
307327 }
328+ if err != nil {
329+ err = fmt .Errorf ("failed to build/test RPM from SRPM:\n %w" , err )
330+ return
331+ }
308332
309333 return
310334}
0 commit comments