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

Martin Storsjo martin at martin.st
Tue May 14 14:02:50 CDT 2019


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>
---
Moved fixing up of the return code to the caller of signal_exit_process.
---
 dlls/ntdll/loader.c  |  3 +++
 dlls/ntdll/process.c |  7 ++++++-
 dlls/ntdll/thread.c  | 14 ++++++++++++--
 3 files changed, 21 insertions(+), 3 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/thread.c b/dlls/ntdll/thread.c
index be4621819b..b17ddda7b6 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 );
 }
 
@@ -316,6 +321,7 @@ void WINAPI RtlExitUserThread( ULONG status )
 {
     static void *prev_teb;
     TEB *teb;
+    int exit_code;
 
     if (status)  /* send the exit code to the server (0 is already the default) */
     {
@@ -332,7 +338,11 @@ void WINAPI RtlExitUserThread( ULONG status )
     {
         LdrShutdownProcess();
         pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
-        signal_exit_process( status );
+        exit_code = status;
+        /* Prevent a nonzero exit code to end up truncated to zero in unix. */
+        if (status != 0 && (status & 0xff) == 0)
+            exit_code = 1;
+        signal_exit_process( exit_code );
     }
 
     LdrShutdownThread();
-- 
2.17.1




More information about the wine-devel mailing list