From 61e10f81bec218b879c5f39b3b19ef1fd2af2db4 Mon Sep 17 00:00:00 2001
From: Jesse Luehrs <doy@tozt.net>
Date: Wed, 22 Dec 2021 20:20:00 -0500
Subject: [PATCH 1/2] make try_status take &self

it doesn't need exclusive access
---
 src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lib.rs b/src/lib.rs
index ed10784..9678d8c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -326,7 +326,7 @@ impl Child {
     /// }
     /// # std::io::Result::Ok(()) });
     /// ```
-    pub fn try_status(&mut self) -> io::Result<Option<ExitStatus>> {
+    pub fn try_status(&self) -> io::Result<Option<ExitStatus>> {
         self.child.lock().unwrap().get_mut().try_wait()
     }
 

From 4438e61dac21d58c29ab4cc7d8152c829977a62d Mon Sep 17 00:00:00 2001
From: Jesse Luehrs <doy@tozt.net>
Date: Wed, 22 Dec 2021 20:25:56 -0500
Subject: [PATCH 2/2] add status_no_drop which takes &self and doesn't drop
 stdin

this is a much more useful capability for an async process library,
since it is much easier to avoid blocking on this call (since it is a
future)
---
 src/lib.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/src/lib.rs b/src/lib.rs
index 9678d8c..cf005e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -352,6 +352,30 @@ impl Child {
     /// ```
     pub fn status(&mut self) -> impl Future<Output = io::Result<ExitStatus>> {
         self.stdin.take();
+        self.status_no_drop()
+    }
+
+    /// Waits for the process to exit.
+    ///
+    /// Unlike `status`, does not drop the stdin handle. You are responsible
+    /// for avoiding deadlocks caused by the child blocking on stdin while the
+    /// parent blocks on waiting for the process to exit.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// # futures_lite::future::block_on(async {
+    /// use async_process::{Command, Stdio};
+    ///
+    /// let child = Command::new("cp")
+    ///     .arg("a.txt")
+    ///     .arg("b.txt")
+    ///     .spawn()?;
+    ///
+    /// println!("exit status: {}", child.status_no_drop().await?);
+    /// # std::io::Result::Ok(()) });
+    /// ```
+    pub fn status_no_drop(&self) -> impl Future<Output = io::Result<ExitStatus>> {
         let child = self.child.clone();
 
         async move {