diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index e3b6c4a5305615a..308bb0130653641 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -700,8 +700,8 @@ def _check_system_limits(): raise NotImplementedError(_system_limited) try: nsems_max = os.sysconf("SC_SEM_NSEMS_MAX") - except (AttributeError, ValueError): - # sysconf not available or setting not available + except (AttributeError, ValueError, OSError): + # sysconf not available, setting not available, or read denied return if nsems_max == -1: # indetermined limit, assume that limit is determined diff --git a/Lib/test/test_concurrent_futures/test_process_pool.py b/Lib/test/test_concurrent_futures/test_process_pool.py index dafbda862c51c24..f6f555261621062 100644 --- a/Lib/test/test_concurrent_futures/test_process_pool.py +++ b/Lib/test/test_concurrent_futures/test_process_pool.py @@ -58,6 +58,24 @@ def test_max_workers_too_large(self): "max_workers must be <= 61"): futures.ProcessPoolExecutor(max_workers=62) + @unittest.skipUnless(hasattr(os, 'sysconf'), 'requires os.sysconf') + def test_sysconf_permission_error(self): + # Issue 155912: ProcessPoolExecutor should handle PermissionError + # from os.sysconf("SC_SEM_NSEMS_MAX") when running under a strict sandbox. + def mock_sysconf(name): + if name == "SC_SEM_NSEMS_MAX": + raise PermissionError(1, "Operation not permitted") + # If it asks for something else, let the real one handle it + # (though normally _check_system_limits only asks for SC_SEM_NSEMS_MAX) + return os_sysconf_orig(name) + + os_sysconf_orig = os.sysconf + with unittest.mock.patch('os.sysconf', side_effect=mock_sysconf): + # Should construct without raising PermissionError + with futures.ProcessPoolExecutor(max_workers=1) as executor: + pass + + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() def test_killed_child(self): # When a child process is abruptly terminated, the whole pool gets diff --git a/Misc/NEWS.d/next/Library/2026-08-17-17-18-00.gh-issue-155912.abcdef.rst b/Misc/NEWS.d/next/Library/2026-08-17-17-18-00.gh-issue-155912.abcdef.rst new file mode 100644 index 000000000000000..4daa745eb7b3d10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-17-17-18-00.gh-issue-155912.abcdef.rst @@ -0,0 +1 @@ +Handle :exc:`PermissionError` from :func:`os.sysconf` in ``concurrent.futures.ProcessPoolExecutor`` when running under a strict sandbox.