未验证 提交 6826f331 编写于 作者: M Matthias Krüger 提交者: GitHub

Rollup merge of #97917 - AronParker:master, r=ChrisDenton

Implement ExitCodeExt for Windows

Fixes #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 https://github.com/rust-lang/rust/pull/93840#issue-1129209143=  as pointed out by ``@eggyal`` in https://github.com/rust-lang/rust/issues/97914#issuecomment-1151076755:

> 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: https://github.com/rust-lang/libs-team/issues/48
......@@ -234,3 +234,26 @@ fn main_thread_handle(&self) -> BorrowedHandle<'_> {
self.handle.main_thread_handle()
}
}
/// 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.
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
pub trait ExitCodeExt: Sealed {
/// Creates a new `ExitCode` from the raw underlying `u32` return value of
/// a process.
///
/// The exit code should not be 259, as this conflicts with the `STILL_ACTIVE`
/// macro returned from the `GetExitCodeProcess` function to signal that the
/// process has yet to run to completion.
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
fn from_raw(raw: u32) -> Self;
}
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
impl ExitCodeExt for process::ExitCode {
fn from_raw(raw: u32) -> Self {
process::ExitCode::from_inner(From::from(raw))
}
}
......@@ -1724,6 +1724,10 @@ impl crate::error::Error for ExitStatusError {}
#[stable(feature = "process_exitcode", since = "1.61.0")]
pub struct ExitCode(imp::ExitCode);
/// Allows extension traits within `std`.
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for ExitCode {}
#[stable(feature = "process_exitcode", since = "1.61.0")]
impl ExitCode {
/// The canonical `ExitCode` for successful termination on this platform.
......@@ -1814,6 +1818,18 @@ fn from(code: u8) -> Self {
}
}
impl AsInner<imp::ExitCode> for ExitCode {
fn as_inner(&self) -> &imp::ExitCode {
&self.0
}
}
impl FromInner<imp::ExitCode> for ExitCode {
fn from_inner(s: imp::ExitCode) -> ExitCode {
ExitCode(s)
}
}
impl Child {
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
/// error is returned.
......
......@@ -707,6 +707,12 @@ fn from(code: u8) -> Self {
}
}
impl From<u32> for ExitCode {
fn from(code: u32) -> Self {
ExitCode(c::DWORD::from(code))
}
}
fn zeroed_startupinfo() -> c::STARTUPINFO {
c::STARTUPINFO {
cb: 0,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册