ntdll: Avoid truncating a nonzero exit code to zero in unix.

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@martin.st>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Martin Storsjo 2019-05-14 22:02:50 +03:00 committed by Alexandre Julliard
parent 4872747b27
commit 044461e8a6
4 changed files with 11 additions and 4 deletions

View File

@ -3264,7 +3264,7 @@ void WINAPI RtlExitUserProcess( DWORD status )
NtTerminateProcess( 0, status ); NtTerminateProcess( 0, status );
LdrShutdownProcess(); LdrShutdownProcess();
NtTerminateProcess( GetCurrentProcess(), status ); NtTerminateProcess( GetCurrentProcess(), status );
exit( status ); exit( get_unix_exit_code( status ));
} }
/****************************************************************** /******************************************************************

View File

@ -247,6 +247,13 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch; return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch;
} }
static inline int get_unix_exit_code( NTSTATUS status )
{
/* prevent a nonzero exit code to end up truncated to zero in unix */
if (status && !(status & 0xff)) return 1;
return status;
}
extern mode_t FILE_umask DECLSPEC_HIDDEN; extern mode_t FILE_umask DECLSPEC_HIDDEN;
extern HANDLE keyed_event DECLSPEC_HIDDEN; extern HANDLE keyed_event DECLSPEC_HIDDEN;
extern SYSTEM_CPU_INFORMATION cpu_info DECLSPEC_HIDDEN; extern SYSTEM_CPU_INFORMATION cpu_info DECLSPEC_HIDDEN;

View File

@ -88,7 +88,7 @@ NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
self = !ret && reply->self; self = !ret && reply->self;
} }
SERVER_END_REQ; SERVER_END_REQ;
if (self && handle) _exit( exit_code ); if (self && handle) _exit( get_unix_exit_code( exit_code ));
return ret; return ret;
} }

View File

@ -291,7 +291,7 @@ static void free_thread_data( TEB *teb )
void abort_thread( int status ) void abort_thread( int status )
{ {
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); 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) _exit( get_unix_exit_code( status ));
signal_exit_thread( status ); signal_exit_thread( status );
} }
@ -332,7 +332,7 @@ void WINAPI RtlExitUserThread( ULONG status )
{ {
LdrShutdownProcess(); LdrShutdownProcess();
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
signal_exit_process( status ); signal_exit_process( get_unix_exit_code( status ));
} }
LdrShutdownThread(); LdrShutdownThread();