[PATCH] ntdll: Avoid truncating a nonzero exit code to zero in unix

André Hentschel nerv at dawncrow.de
Tue May 14 07:20:40 CDT 2019


On 13.05.19 12:30, Martin Storsjo wrote:
> On Windows, the exit codes can use the full 32 bit range, while
> on unix, they are truncated to the lowest 8 bits. If the intended
> exit code is nonzero, to indicate failure, but the lower 8 bits
> are zero (like when winedbg tries to exit with EXCEPTION_WINE_STUB,
> 80000100), the observed exit code used to be zero, indicating
> successful execution.
> 
> Signed-off-by: Martin Storsjo <martin at martin.st>
> ---
> This is an alternative to https://source.winehq.org/patches/data/164482
> (fixing the same issue in winedbg), by keeping the full range of the
> winedbg exit code and just avoiding the issue right before calling
> exit/_exit.
> ---
>   dlls/ntdll/loader.c         | 3 +++
>   dlls/ntdll/process.c        | 7 ++++++-
>   dlls/ntdll/signal_arm.c     | 3 +++
>   dlls/ntdll/signal_arm64.c   | 3 +++
>   dlls/ntdll/signal_i386.c    | 3 +++
>   dlls/ntdll/signal_powerpc.c | 3 +++
>   dlls/ntdll/signal_x86_64.c  | 3 +++
>   dlls/ntdll/thread.c         | 7 ++++++-
>   8 files changed, 30 insertions(+), 2 deletions(-)
> 
> diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
> index 994ff6f215..0279c81aa7 100644
> --- a/dlls/ntdll/loader.c
> +++ b/dlls/ntdll/loader.c
> @@ -3264,6 +3264,9 @@ void WINAPI RtlExitUserProcess( DWORD status )
>       NtTerminateProcess( 0, status );
>       LdrShutdownProcess();
>       NtTerminateProcess( GetCurrentProcess(), status );
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       exit( status );
>   }
>   
> diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c
> index 573a7a771d..ea3565cb1c 100644
> --- a/dlls/ntdll/process.c
> +++ b/dlls/ntdll/process.c
> @@ -88,7 +88,12 @@ NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
>           self = !ret && reply->self;
>       }
>       SERVER_END_REQ;
> -    if (self && handle) _exit( exit_code );
> +    if (self && handle) {
> +        /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +        if (exit_code != 0 && (exit_code & 0xff) == 0)
> +            exit_code = 1;
> +        _exit( exit_code );
> +    }
>       return ret;
>   }
>   
> diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
> index e01c8ce219..4f4dcced05 100644
> --- a/dlls/ntdll/signal_arm.c
> +++ b/dlls/ntdll/signal_arm.c
> @@ -1396,6 +1396,9 @@ void signal_exit_thread( int status )
>    */
>   void signal_exit_process( int status )
>   {
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       call_thread_exit_func( status, exit, NtCurrentTeb() );
>   }
>   
> diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
> index 8114d45fef..e56dd6b1ab 100644
> --- a/dlls/ntdll/signal_arm64.c
> +++ b/dlls/ntdll/signal_arm64.c
> @@ -1171,6 +1171,9 @@ void signal_exit_thread( int status )
>    */
>   void signal_exit_process( int status )
>   {
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       exit( status );
>   }
>   
> diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
> index 053c87da83..a89ff20fd6 100644
> --- a/dlls/ntdll/signal_i386.c
> +++ b/dlls/ntdll/signal_i386.c
> @@ -2817,6 +2817,9 @@ void signal_exit_thread( int status )
>    */
>   void signal_exit_process( int status )
>   {
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       call_thread_exit_func( status, exit );
>   }
>   
> diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
> index 86398d8f54..a5cce9bae3 100644
> --- a/dlls/ntdll/signal_powerpc.c
> +++ b/dlls/ntdll/signal_powerpc.c
> @@ -1240,6 +1240,9 @@ void signal_exit_thread( int status )
>    */
>   void signal_exit_process( int status )
>   {
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       exit( status );
>   }
>   
> diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
> index 21e7098876..140e11b491 100644
> --- a/dlls/ntdll/signal_x86_64.c
> +++ b/dlls/ntdll/signal_x86_64.c
> @@ -4603,6 +4603,9 @@ void signal_exit_thread( int status )
>    */
>   void signal_exit_process( int status )
>   {
> +    /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +    if (status != 0 && (status & 0xff) == 0)
> +        status = 1;
>       call_thread_exit_func( status, exit );
>   }
>   
> diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
> index be4621819b..66a92eb3fc 100644
> --- a/dlls/ntdll/thread.c
> +++ b/dlls/ntdll/thread.c
> @@ -291,7 +291,12 @@ static void free_thread_data( TEB *teb )
>   void abort_thread( int status )
>   {
>       pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
> -    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status );
> +    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) {
> +        /* Prevent a nonzero exit code to end up truncated to zero in unix. */
> +        if (status != 0 && (status & 0xff) == 0)
> +            status = 1;
> +        _exit( status );
> +    }
>       signal_exit_thread( status );
>   }
>   
> 

Signed-off-by: André Hentschel <nerv at dawncrow.de>



More information about the wine-devel mailing list