Writing to stdin of a spawned command

Hello,

I have (I believe) successfully written some code to write to stdin of a spawned command - I lifted the code from StackOverflow. Here is the snippet from my repository:

let command_stdin = match command.stdin.as_mut() {
    Some(command_stdin) => command_stdin,
    None                => {
        eprintln!("Unable to get mutable reference to stdin.");
        process::exit(63);
    },
};
match command_stdin
    .write_all(
        clear_text.as_bytes()
    )
{
    Ok(_)    => (),
    Err(err) => {
        eprintln!("Unable to write bytes to stdin of encryption process: '{err}'");
        process::exit(64);
    },
};

// Close stdin to finish and avoid indefinite blocking
drop(command_stdin);

Until today I have never run clippy. Now that I've run clippy against my software I get the following error:

    Checking puppet-retrieve-ssh-keys v0.2.3 (/home/mzagrabe/git/internal/puppet-retrieve-ssh-keys)
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
   --> src/puppet_retrieve_ssh_keys/writer.rs:153:9
    |
153 |         drop(command_stdin);
    |         ^^^^^^^^^^^^^^^^^^^
    |
note: argument has type `&mut std::process::ChildStdin`
   --> src/puppet_retrieve_ssh_keys/writer.rs:153:14
    |
153 |         drop(command_stdin);
    |              ^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
    = note: `#[deny(clippy::drop_ref)]` on by default

error: could not compile `puppet-retrieve-ssh-keys` due to previous error

To which I've fixed the clippy error by replacing the top line in my code with:

let mut command_stdin = match command.stdin.take() {

I have a few questions...

  1. I'm having a hard time finding documentation on the ".take()" function/method. Could anyone point me in the right direction to find the docs for it?

  2. Do I need the "drop()" on the command_stdin? I copied the initial code from StackOverflow and I'm not certain of its correctness.

  3. If folks have any feedback on my code for writing to the stdin of a spawned command please let me know.

Thanks for the help!

-m

command is, if I understand correctly, a Child (created by Command::spawn). Child::stdin is Option<ChildStdin>, therefore, take should be a method on Option - and indeed it is here.

It will be dropped at the end of surrounding scope, but if you need to close the pipe before that (essentially, to send an EOF to the spawned process) - then, yes, you heed to drop it explicitly. If you code worked before replacing as_mut with take, though, I'd expect that command_stdin was already being dropped correctly.

Hi @Cerber-Ursi,

Thank you for the reply - and help! I l lost my mind and skipped over the Option and simply looked at the ChildStdin docs. Thanks for pointing that out!

Since the code was working with the mutable reference and the stdin wasn't being "dropped" until the end of the block (even though the code made it looked like it was being dropped), I probably don't need the explicit drop when I "take" the ChildStdin. I wonder if that is generally the case for these "simple" 'write to stdin of a spawned process' scenarios.

Anyhow. Thank you again for the prompt and insightful help!

Much appreciated.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.