Need help killing a process I started

So this is on linux. I'm starting a process, and later on I need to stop it. Things work basically fine, excep that after killing said process, it lingers as "defunct" in the process list. I'd like to fix that. Googling leads me to believe "the parent process is monitoring the child process", but I don't understand what "monitoring" means in this context, and I did not consciously set up any monitoring.

Here's the code, lightly edited for brevity:

  fn start_recording(&self, buffer: &mut BufHandler) -> (NaiveDateTime, u32, String) {
    let (viddir, filename, datetime) = // snip

    let recorder = Command::new("/usr/bin/gpu-screen-recorder")
      .args(["-w", "DisplayPort-0"])
      .args(["-c", "mkv"])
      .args(["-k", "hevc"])
      .args(["-ac", "opus"])
      .args(["-f", "60"])
      .args(["-cursor", "yes"])
      .args(["-restore-portal-session", "yes"])
      .args(["-cr", "limited"])
      .args(["-encoder", "gpu"])
      .args(["-q", "very_high"])
      .args(["-a", "device:default_output"])
      .args(["-o", &format!("{viddir}/{filename}.mkv")])
      .stderr(Stdio::null())
      .spawn()
      .unwrap();
    (datetime, recorder.id(), filename)
  }

  fn end_recording(&mut self) {
    let (pid, chapterfile, viddir, filename) = //snip

    spawn(async move {
      let output = Command::new("kill")
        .args(["-SIGINT", &pid])
        .output()
        .expect("Killing failed");
      println!("Killed recorder {pid} with status {}", output.status);
      io::stdout().write_all(&output.stdout).unwrap();
      io::stderr().write_all(&output.stderr).unwrap();

      let mkvfile = format!("{viddir}/{filename}.mkv");
      let outfile = format!("{viddir}/{filename}_final.mkv");

      let merger = Command::new("/usr/bin/mkvmerge")
        .args(["--chapters", &chapterfile])
        .args(["-o", &outfile])
        .args([&mkvfile])
        .stdout(Stdio::null())
        .output()
        .expect("Merging failed");
      io::stderr().write_all(&merger.stderr).unwrap();
    });
  }

I'm spawning off the kill command because more stuff happens in that task, and I want my main task to resume kind of asap.

So, let me reiterate, functionality is fine, just the killing doesn't work as I want it to. When I end my process, the child process ends too. The merger works, too, so it does not seem my code is stuck somehow.

Any help appreciated, if I should provide more information, please kindly let me know :slight_smile:

Can't you keep the recorder around and just wait for it after killing (of even kill it through the corresponding method, without spawning separate command)?

Ohhh I did not see that Child has a kill method. I am however certain I need to send SIGINT, so I hope that's what the method does. wait is not an option, the recorder won't end itself, so I need to send an external signal.

Checked the docs - nope, it's the forced exit, that is, SIGKILL. In this case you might want to use nix::sys::signal::kill, if you're OK for this to be system-specific (and it seems you are).

I mean, you likely want to call wait after you sent the signal - to tell the OS "yes, I know this child process has ended, you may clean it up now".

1 Like

My what a dance, why do I get a u32 pid from Child, but can only stick an i32 in for nix::sys::signal::Pid? Anyways, should be fine for now, it all works out. Thanks a lot @Cerber-Ursi!