gh-125842: Fix sys.exit(0xffff_ffff) on Windows (#125896)

On Windows, `long` is a signed 32-bit integer so it can't represent
`0xffff_ffff` without overflow. Windows exit codes are unsigned 32-bit
integers, so if a child process exits with `-1`, it will be represented
as `0xffff_ffff`.

Also fix a number of other possible cases where `_Py_HandleSystemExit`
could return with an exception set, leading to a `SystemError` (or
fatal error in debug builds) later on during shutdown.
This commit is contained in:
Sam Gross 2024-10-24 12:03:50 -04:00 committed by GitHub
parent e545ead66c
commit ad6110a93f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 65 additions and 35 deletions

View file

@ -206,6 +206,20 @@ class SysModuleTest(unittest.TestCase):
self.assertEqual(out, b'')
self.assertEqual(err, b'')
# gh-125842: Windows uses 32-bit unsigned integers for exit codes
# so a -1 exit code is sometimes interpreted as 0xffff_ffff.
rc, out, err = assert_python_failure('-c', 'import sys; sys.exit(0xffff_ffff)')
self.assertIn(rc, (-1, 0xff, 0xffff_ffff))
self.assertEqual(out, b'')
self.assertEqual(err, b'')
# Overflow results in a -1 exit code, which may be converted to 0xff
# or 0xffff_ffff.
rc, out, err = assert_python_failure('-c', 'import sys; sys.exit(2**128)')
self.assertIn(rc, (-1, 0xff, 0xffff_ffff))
self.assertEqual(out, b'')
self.assertEqual(err, b'')
# call with integer argument
with self.assertRaises(SystemExit) as cm:
sys.exit(42)