@@ -132,7 +132,11 @@ impl std::fmt::Debug for SpawnError {
132
132
///
133
133
/// This only starts a Viewer process: if you'd like to connect to it and start sending data, refer
134
134
/// to [`crate::RecordingStream::connect`] or use [`crate::RecordingStream::spawn`] directly.
135
+ #[ allow( unsafe_code) ]
135
136
pub fn spawn ( opts : & SpawnOptions ) -> Result < ( ) , SpawnError > {
137
+ #[ cfg( target_family = "unix" ) ]
138
+ use std:: os:: unix:: process:: CommandExt as _;
139
+
136
140
use std:: { net:: TcpStream , process:: Command , time:: Duration } ;
137
141
138
142
// NOTE: These are indented on purpose, it just looks better and reads easier.
@@ -244,17 +248,32 @@ pub fn spawn(opts: &SpawnOptions) -> Result<(), SpawnError> {
244
248
}
245
249
}
246
250
247
- let rerun_bin = Command :: new ( & executable_path)
248
- // By default stdin is inherited which may cause issues in some debugger setups.
249
- // Also, there's really no reason to forward stdin to the child process in this case.
250
- // `stdout`/`stderr` we leave at default inheritance because it can be useful to see the Viewer's output.
251
+ let mut rerun_bin = Command :: new ( & executable_path) ;
252
+
253
+ // By default stdin is inherited which may cause issues in some debugger setups.
254
+ // Also, there's really no reason to forward stdin to the child process in this case.
255
+ // `stdout`/`stderr` we leave at default inheritance because it can be useful to see the Viewer's output.
256
+ rerun_bin
251
257
. stdin ( std:: process:: Stdio :: null ( ) )
252
258
. arg ( format ! ( "--port={port}" ) )
253
259
. arg ( format ! ( "--memory-limit={memory_limit}" ) )
254
260
. arg ( "--expect-data-soon" )
255
- . args ( opts. extra_args . clone ( ) )
256
- . spawn ( )
257
- . map_err ( map_err) ?;
261
+ . args ( opts. extra_args . clone ( ) ) ;
262
+
263
+ // SAFETY: This code is only run in the child fork, we are not modifying any memory
264
+ // that is shared with the parent process.
265
+ #[ cfg( target_family = "unix" ) ]
266
+ unsafe {
267
+ rerun_bin. pre_exec ( || {
268
+ // On unix systems, we want to make sure that the child process becomes its
269
+ // own session leader, so that it doesn't die if the parent process crashes
270
+ // or is killed.
271
+ libc:: setsid ( ) ;
272
+
273
+ Ok ( ( ) )
274
+ } )
275
+ } ;
276
+ rerun_bin. spawn ( ) . map_err ( map_err) ?;
258
277
259
278
if opts. wait_for_bind {
260
279
// Give the newly spawned Rerun Viewer some time to bind.
0 commit comments