@@ -181,14 +181,6 @@ pub fn partitions_of(dev: &Utf8Path) -> Result<PartitionTable> {
181
181
182
182
pub struct LoopbackDevice {
183
183
pub dev : Option < Utf8PathBuf > ,
184
- // Handle to the cleanup helper process
185
- cleanup_handle : Option < LoopbackCleanupHandle > ,
186
- }
187
-
188
- /// Handle to manage the cleanup helper process for loopback devices
189
- struct LoopbackCleanupHandle {
190
- /// Child process handle
191
- child : std:: process:: Child ,
192
184
}
193
185
194
186
impl LoopbackDevice {
@@ -216,15 +208,7 @@ impl LoopbackDevice {
216
208
. run_get_string ( ) ?;
217
209
let dev = Utf8PathBuf :: from ( dev. trim ( ) ) ;
218
210
tracing:: debug!( "Allocated loopback {dev}" ) ;
219
-
220
- // Try to spawn cleanup helper process - if it fails, make it fatal
221
- let cleanup_handle = Self :: spawn_cleanup_helper ( dev. as_str ( ) )
222
- . context ( "Failed to spawn loopback cleanup helper" ) ?;
223
-
224
- Ok ( Self {
225
- dev : Some ( dev) ,
226
- cleanup_handle : Some ( cleanup_handle) ,
227
- } )
211
+ Ok ( Self { dev : Some ( dev) } )
228
212
}
229
213
230
214
// Access the path to the loopback block device.
@@ -233,49 +217,13 @@ impl LoopbackDevice {
233
217
self . dev . as_deref ( ) . unwrap ( )
234
218
}
235
219
236
- /// Spawn a cleanup helper process that will clean up the loopback device
237
- /// if the parent process dies unexpectedly
238
- fn spawn_cleanup_helper ( device_path : & str ) -> Result < LoopbackCleanupHandle > {
239
- use std:: process:: { Command , Stdio } ;
240
-
241
- // Get the path to our own executable
242
- let self_exe =
243
- std:: fs:: read_link ( "/proc/self/exe" ) . context ( "Failed to read /proc/self/exe" ) ?;
244
-
245
- // Create the helper process
246
- let mut cmd = Command :: new ( self_exe) ;
247
- cmd. args ( [ "loopback-cleanup-helper" , "--device" , device_path] ) ;
248
-
249
- // Set environment variable to indicate this is a cleanup helper
250
- cmd. env ( "BOOTC_LOOPBACK_CLEANUP_HELPER" , "1" ) ;
251
-
252
- // Set up stdio to redirect to /dev/null
253
- cmd. stdin ( Stdio :: null ( ) ) ;
254
- cmd. stdout ( Stdio :: null ( ) ) ;
255
- cmd. stderr ( Stdio :: null ( ) ) ;
256
-
257
- // Spawn the process
258
- let child = cmd
259
- . spawn ( )
260
- . context ( "Failed to spawn loopback cleanup helper" ) ?;
261
-
262
- Ok ( LoopbackCleanupHandle { child } )
263
- }
264
-
265
220
// Shared backend for our `close` and `drop` implementations.
266
221
fn impl_close ( & mut self ) -> Result < ( ) > {
267
222
// SAFETY: This is the only place we take the option
268
223
let Some ( dev) = self . dev . take ( ) else {
269
224
tracing:: trace!( "loopback device already deallocated" ) ;
270
225
return Ok ( ( ) ) ;
271
226
} ;
272
-
273
- // Kill the cleanup helper since we're cleaning up normally
274
- if let Some ( mut cleanup_handle) = self . cleanup_handle . take ( ) {
275
- // Send SIGTERM to the child process
276
- let _ = cleanup_handle. child . kill ( ) ;
277
- }
278
-
279
227
Command :: new ( "losetup" ) . args ( [ "-d" , dev. as_str ( ) ] ) . run ( )
280
228
}
281
229
@@ -292,46 +240,6 @@ impl Drop for LoopbackDevice {
292
240
}
293
241
}
294
242
295
- /// Main function for the loopback cleanup helper process
296
- /// This function does not return - it either exits normally or via signal
297
- pub async fn run_loopback_cleanup_helper ( device_path : & str ) -> Result < ( ) > {
298
- // Check if we're running as a cleanup helper
299
- if std:: env:: var ( "BOOTC_LOOPBACK_CLEANUP_HELPER" ) . is_err ( ) {
300
- anyhow:: bail!( "This function should only be called as a cleanup helper" ) ;
301
- }
302
-
303
- // Set up death signal notification - we want to be notified when parent dies
304
- rustix:: process:: set_parent_process_death_signal ( Some ( rustix:: process:: Signal :: TERM ) )
305
- . context ( "Failed to set parent death signal" ) ?;
306
-
307
- // Wait for SIGTERM (either from parent death or normal cleanup)
308
- tokio:: signal:: unix:: signal ( tokio:: signal:: unix:: SignalKind :: terminate ( ) )
309
- . expect ( "Failed to create signal stream" )
310
- . recv ( )
311
- . await ;
312
-
313
- // Clean up the loopback device
314
- let status = std:: process:: Command :: new ( "losetup" )
315
- . args ( [ "-d" , device_path] )
316
- . status ( ) ;
317
-
318
- match status {
319
- Ok ( exit_status) if exit_status. success ( ) => {
320
- // Log to systemd journal instead of stderr
321
- tracing:: info!( "Cleaned up leaked loopback device {}" , device_path) ;
322
- std:: process:: exit ( 0 ) ;
323
- }
324
- Ok ( _) => {
325
- tracing:: error!( "Failed to clean up loopback device {}" , device_path) ;
326
- std:: process:: exit ( 1 ) ;
327
- }
328
- Err ( e) => {
329
- tracing:: error!( "Error cleaning up loopback device {}: {}" , device_path, e) ;
330
- std:: process:: exit ( 1 ) ;
331
- }
332
- }
333
- }
334
-
335
243
/// Parse key-value pairs from lsblk --pairs.
336
244
/// Newer versions of lsblk support JSON but the one in CentOS 7 doesn't.
337
245
fn split_lsblk_line ( line : & str ) -> HashMap < String , String > {
0 commit comments