Skip to content

Implement ExitCodeExt for Windows #48

Closed
@AronParker

Description

@AronParker

Proposal

Problem statement

On Windows it is common for applications to return HRESULT (i32) or DWORD (u32) values. The newly stabilized ExitCode provides an excellent fit for propagating these values, because std::process::exit exits immediately and 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 proposal 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.

Motivation, use-cases

  • COM based components as well as newer Win32 based-functions make extensive use of HRESULT (i32) values, which is a universal success and error code on Windows designed to represent every error code from multiple facilities.

  • GUI applications use a message loop to process their events. On windows, once the WM_QUIT message has been received, the application is requested to return the exit code in wParam, which was originally sent using the PostQuitMessage function. It takes an i32, which is to be returned from main. Using std::process::exit can result in error conditions such as an unhandled exception 0x80000003 inside the ExitProcess function. In contrast, using ExitCode allows running all destructors and unregistering window classes which prevent the exception.

  • Win32 errors (system error codes) received by GetLastError are also popular to return as an exit code, which do not fit inside an u8.

Solution sketches

/// 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.
    ///
    /// 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.
    #[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))
    }
}

Links and related work

Original suggestion
Implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions