Skip to content

Commit 5fbe1de

Browse files
authored
Rollup merge of rust-lang#97917 - AronParker:master, r=ChrisDenton
Implement ExitCodeExt for Windows Fixes rust-lang#97914 ### Motivation: On Windows it is common for applications to return `HRESULT` (`i32`) or `DWORD` (`u32`) values. These stem from COM based components ([HRESULTS](https://docs.microsoft.com/en-us/windows/win32/api/objbase/nf-objbase-coinitialize)), Win32 errors ([GetLastError](https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror)), GUI applications ([WM_QUIT](https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-quit)) and more. The newly stabilized `ExitCode` provides an excellent fit for propagating these values, because `std::process::exit` does not run deconstructors which can result in errors. However, `ExitCode` currently only implements `From<u8> for ExitCode`, which disallows the full range of `i32`/`u32` values. This pull requests attempts to address that shortcoming by providing windows specific extensions that accept a `u32` value (which covers all possible `HRESULTS` and Win32 errors) analog to [ExitStatusExt::from_raw](https://doc.rust-lang.org/std/os/windows/process/trait.ExitStatusExt.html#tymethod.from_raw). This was also intended by the original Stabilization rust-lang#93840 (comment) as pointed out by ``@eggyal`` in rust-lang#97914 (comment): > Issues around platform specific representations: We resolved this issue by changing the return type of report from i32 to the opaque type ExitCode. __That way we can change the underlying representation without affecting the API, letting us offer full support for platform specific exit code APIs in the future.__ [Emphasis added] ### API ```rust /// Windows-specific extensions to [`process::ExitCode`]. /// /// This trait is sealed: it cannot be implemented outside the standard library. /// This is so that future additional methods are not breaking changes. #[stable(feature = "windows_process_exit_code_from", since = "1.63.0")] pub trait ExitCodeExt: Sealed { /// Creates a new `ExitCode` from the raw underlying `u32` return value of /// a process. #[stable(feature = "windows_process_exit_code_from", since = "1.63.0")] fn from_raw(raw: u32) -> Self; } #[stable(feature = "windows_process_exit_code_from", since = "1.63.0")] impl ExitCodeExt for process::ExitCode { fn from_raw(raw: u32) -> Self { process::ExitCode::from_inner(From::from(raw)) } } ``` ### Misc I apologize in advance if I misplaced any attributes regarding stabilzation, as far as I learned traits are insta-stable so I chose to make them stable. If this is an error, please let me know and I'll correct it. I also added some additional machinery to make it work, analog to [ExitStatus](https://doc.rust-lang.org/std/process/struct.ExitStatus.html#). EDIT: Proposal: rust-lang/libs-team#48
2 parents 4328714 + 2de8bdb commit 5fbe1de

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

std/src/os/windows/process.rs

+23
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,26 @@ impl ChildExt for process::Child {
234234
self.handle.main_thread_handle()
235235
}
236236
}
237+
238+
/// Windows-specific extensions to [`process::ExitCode`].
239+
///
240+
/// This trait is sealed: it cannot be implemented outside the standard library.
241+
/// This is so that future additional methods are not breaking changes.
242+
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
243+
pub trait ExitCodeExt: Sealed {
244+
/// Creates a new `ExitCode` from the raw underlying `u32` return value of
245+
/// a process.
246+
///
247+
/// The exit code should not be 259, as this conflicts with the `STILL_ACTIVE`
248+
/// macro returned from the `GetExitCodeProcess` function to signal that the
249+
/// process has yet to run to completion.
250+
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
251+
fn from_raw(raw: u32) -> Self;
252+
}
253+
254+
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
255+
impl ExitCodeExt for process::ExitCode {
256+
fn from_raw(raw: u32) -> Self {
257+
process::ExitCode::from_inner(From::from(raw))
258+
}
259+
}

std/src/process.rs

+16
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,10 @@ impl crate::error::Error for ExitStatusError {}
17241724
#[stable(feature = "process_exitcode", since = "1.61.0")]
17251725
pub struct ExitCode(imp::ExitCode);
17261726

1727+
/// Allows extension traits within `std`.
1728+
#[unstable(feature = "sealed", issue = "none")]
1729+
impl crate::sealed::Sealed for ExitCode {}
1730+
17271731
#[stable(feature = "process_exitcode", since = "1.61.0")]
17281732
impl ExitCode {
17291733
/// The canonical `ExitCode` for successful termination on this platform.
@@ -1814,6 +1818,18 @@ impl From<u8> for ExitCode {
18141818
}
18151819
}
18161820

1821+
impl AsInner<imp::ExitCode> for ExitCode {
1822+
fn as_inner(&self) -> &imp::ExitCode {
1823+
&self.0
1824+
}
1825+
}
1826+
1827+
impl FromInner<imp::ExitCode> for ExitCode {
1828+
fn from_inner(s: imp::ExitCode) -> ExitCode {
1829+
ExitCode(s)
1830+
}
1831+
}
1832+
18171833
impl Child {
18181834
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
18191835
/// error is returned.

std/src/sys/windows/process.rs

+6
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,12 @@ impl From<u8> for ExitCode {
707707
}
708708
}
709709

710+
impl From<u32> for ExitCode {
711+
fn from(code: u32) -> Self {
712+
ExitCode(c::DWORD::from(code))
713+
}
714+
}
715+
710716
fn zeroed_startupinfo() -> c::STARTUPINFO {
711717
c::STARTUPINFO {
712718
cb: 0,

0 commit comments

Comments
 (0)