From 88528a1a32468dfdc99bcce56f9db19aa6d650a8 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 19:10:34 +0100 Subject: [PATCH 1/7] Introduce io::ErrorKind::SubprocessFailed and add a From impl We add this to the existing feature gate exit_status_error, since we will probably want to stabilise this trait impl along with the new type - or not at all. Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 40 +++++++++++++++++++++++++++++++++++++ library/std/src/process.rs | 7 +++++++ 2 files changed, 47 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 51666c0a3c7f1..141545b1440dd 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -284,6 +284,45 @@ pub enum ErrorKind { #[stable(feature = "out_of_memory_error", since = "1.54.0")] OutOfMemory, + /// Subprocess failed. + /// + /// A subprocess (eg, run by a + /// [`Command`](care::process::Command)) failed. + /// + /// Often wraps an + /// [`ExitStatusError`](crate::process::ExitStatusError), + /// (perhaps via `?` and `Into`), in which case + /// [`io::Error::get_ref`](crate::io::error::get_ref) or + /// [`std::error::Error::source`](crate::error::Error::source) + /// is the `ExitStatusError`, + /// allowing the subprocess's exit status to be obtained. + /// + /// (The exit code, exit status, or wait status is generally *not* + /// available via + /// [`io::Error::raw_os_error`](crate::io::Error::raw_os_error), + /// since process exit codes are not generally the same as OS + /// error codes..) + /// + /// # Example + /// ``` + /// #![feature(exit_status_error)] + /// use std::process::{Command, ExitStatusError}; + /// + /// fn system(shellcmd: &str) -> Result<(), std::io::Error> { + /// Command::new("sh").args(&["-c",shellcmd]).status()?.exit_ok()?; + /// Ok(()) + /// } + /// + /// # if cfg!(unix) { + /// let err = system("exit 23").unwrap_err(); + /// let exit_error: &ExitStatusError = err.get_ref().unwrap().downcast_ref().unwrap(); + /// assert_eq!(err.to_string(), "process exited unsuccessfully: exit status: 23"); + /// assert_eq!(exit_error.code(), Some(23)); + /// # } + /// ``` + #[unstable(feature = "exit_status_error", issue = "84908")] + SubprocessFailed, + // "Unusual" error kinds which do not correspond simply to (sets // of) OS error codes, should be added just above this comment. // `Other` and `Uncategorised` should remain at the end: @@ -350,6 +389,7 @@ impl ErrorKind { ResourceBusy => "resource busy", StaleNetworkFileHandle => "stale network file handle", StorageFull => "no storage space", + SubprocessFailed => "subprocess failed", TimedOut => "timed out", TooManyLinks => "too many links", Uncategorized => "uncategorized error", diff --git a/library/std/src/process.rs b/library/std/src/process.rs index c9b21fcf9c6d2..2d9ab9ee360fb 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1636,6 +1636,13 @@ impl fmt::Display for ExitStatusError { #[unstable(feature = "exit_status_error", issue = "84908")] impl crate::error::Error for ExitStatusError {} +#[unstable(feature = "exit_status_error", issue = "84908")] +impl From for io::Error { + fn from(ese: ExitStatusError) -> io::Error { + io::Error::new(io::ErrorKind::SubprocessFailed, ese) + } +} + /// This type represents the status code a process can return to its /// parent under normal termination. /// From 703c994e545c5f5144dcc19e91c1c430f40046b9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 20:51:44 +0100 Subject: [PATCH 2/7] Fix typo in doc --- library/std/src/io/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 141545b1440dd..7c93ca3af85ec 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -287,7 +287,7 @@ pub enum ErrorKind { /// Subprocess failed. /// /// A subprocess (eg, run by a - /// [`Command`](care::process::Command)) failed. + /// [`Command`](crate::process::Command)) failed. /// /// Often wraps an /// [`ExitStatusError`](crate::process::ExitStatusError), From c524bf6527ba18735218b273b37ea76226a7acac Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 24 Aug 2021 22:00:57 +0100 Subject: [PATCH 3/7] Fix typo in doc (again) Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 7c93ca3af85ec..3912052a0abd7 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -292,7 +292,7 @@ pub enum ErrorKind { /// Often wraps an /// [`ExitStatusError`](crate::process::ExitStatusError), /// (perhaps via `?` and `Into`), in which case - /// [`io::Error::get_ref`](crate::io::error::get_ref) or + /// [`io::Error::get_ref`](crate::io::Error::get_ref) or /// [`std::error::Error::source`](crate::error::Error::source) /// is the `ExitStatusError`, /// allowing the subprocess's exit status to be obtained. From 17f61bb9b63643e81fdade1441e3fa917e31eff2 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 25 Aug 2021 00:50:39 +0100 Subject: [PATCH 4/7] process tests: Add (brittle-ish) test for execing bad binary This should be fine on all actual Unix platforms since errno values are quite conventional, especially very basic ones like ENOENT. Signed-off-by: Ian Jackson --- library/std/src/process/tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index bc71c150550a4..bfdf1419f720d 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -129,7 +129,11 @@ fn test_process_status() { #[test] fn test_process_output_fail_to_start() { match Command::new("/no-binary-by-this-name-should-exist").output() { - Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound), + Err(e) => { + assert_eq!(e.kind(), ErrorKind::NotFound); + #[cfg(unix)] // Feel free to adjust/disable if this varies on some platform + assert_eq!(e.to_string(), "No such file or directory (os error 2)"); + }, Ok(..) => panic!(), } } From 13d781c00858f8580024381e2081ea1e7175c5f5 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 25 Aug 2021 01:02:18 +0100 Subject: [PATCH 5/7] io::ErrorKind::SubprocessFailed: clarify/correct doc Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 3912052a0abd7..15611b86b2234 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -289,7 +289,7 @@ pub enum ErrorKind { /// A subprocess (eg, run by a /// [`Command`](crate::process::Command)) failed. /// - /// Often wraps an + /// Often an [`io::Error`](`crate::io::Error`) with this kind wraps an /// [`ExitStatusError`](crate::process::ExitStatusError), /// (perhaps via `?` and `Into`), in which case /// [`io::Error::get_ref`](crate::io::Error::get_ref) or From 2bfb7ebd7c3de448c7282f9e295f9e344aaf55b6 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 25 Aug 2021 01:07:17 +0100 Subject: [PATCH 6/7] io::ExitStatusError: mention conversion to io::Error Signed-off-by: Ian Jackson --- library/std/src/process.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 2d9ab9ee360fb..48f4871424d21 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1530,6 +1530,9 @@ impl crate::sealed::Sealed for ExitStatusError {} /// /// Produced by the [`.exit_ok`](ExitStatus::exit_ok) method on [`ExitStatus`]. /// +/// Implements [`Into`], producing an [`io::Error`] +/// of kind [`Subprocessfailed`](io::ErrorKind::SubprocessFailed). +/// /// # Examples /// /// ``` From 95b6c8f24eebea3c24685f51e7ef24a439a3fdb8 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 25 Aug 2021 01:10:05 +0100 Subject: [PATCH 7/7] Tidy fix Signed-off-by: Ian Jackson --- library/std/src/process/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index bfdf1419f720d..72186f8953f7c 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -133,7 +133,7 @@ fn test_process_output_fail_to_start() { assert_eq!(e.kind(), ErrorKind::NotFound); #[cfg(unix)] // Feel free to adjust/disable if this varies on some platform assert_eq!(e.to_string(), "No such file or directory (os error 2)"); - }, + } Ok(..) => panic!(), } }