Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-40423: Optimization: use close_range(2) if available #22651

Merged
merged 4 commits into from
Oct 11, 2020

Conversation

kevans91
Copy link
Contributor

@kevans91 kevans91 commented Oct 11, 2020

close_range(2) should be preferred at all times if it's available, otherwise we'll use closefrom(2) if available with a fallback to fdwalk(3) or plain old loop over fd range in order of most efficient to least.

[note that this version does check for ENOSYS, but currently ignores all other errors]

https://bugs.python.org/issue40423

Automerge-Triggered-By: @pablogsal

@gpshead gpshead added 🤖 automerge type-feature A feature request or enhancement labels Oct 11, 2020
@miss-islington
Copy link
Contributor

@kevans91: Status check is done, and it's a failure ❌ .

Modules/posixmodule.c Outdated Show resolved Hide resolved
@pablogsal
Copy link
Member

pablogsal commented Oct 11, 2020

@gpshead I have removed the automerge in case my previous comment is not something I am missing, feel free to add it back if everything looks ok

@miss-islington
Copy link
Contributor

@kevans91: Status check is done, and it's a success ✅ .

@miss-islington miss-islington merged commit 1800c60 into python:master Oct 11, 2020
@python python deleted a comment from bedevere-bot Oct 11, 2020
@bedevere-bot
Copy link

bedevere-bot commented Oct 11, 2020

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot s390x RHEL8 3.x has failed when building commit 1800c60.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/all/#builders/509/builds/172) and take a look at the build logs.
  4. Check if the failure is related to this commit (1800c60) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/all/#builders/509/builds/172

Summary of the results of the build (if available):

== Tests result: ENV CHANGED ==

409 tests OK.

10 slowest tests:

  • test_concurrent_futures: 3 min 28 sec
  • test_multiprocessing_spawn: 2 min 4 sec
  • test_peg_generator: 1 min 53 sec
  • test_unparse: 1 min 53 sec
  • test_gdb: 1 min 36 sec
  • test_multiprocessing_forkserver: 1 min 27 sec
  • test_capi: 1 min 27 sec
  • test_tokenize: 1 min 11 sec
  • test_asyncio: 1 min 6 sec
  • test_multiprocessing_fork: 1 min 5 sec

1 test altered the execution environment:
test_logging

14 tests skipped:
test_devpoll test_ioctl test_kqueue test_msilib test_nis
test_ossaudiodev test_startfile test_tix test_tk test_ttk_guionly
test_winconsoleio test_winreg test_winsound test_zipfile64

Total duration: 7 min 31 sec

Click to see traceback logs
remote: Enumerating objects: 22, done.        
remote: Counting objects:   4% (1/22)        
remote: Counting objects:   9% (2/22)        
remote: Counting objects:  13% (3/22)        
remote: Counting objects:  18% (4/22)        
remote: Counting objects:  22% (5/22)        
remote: Counting objects:  27% (6/22)        
remote: Counting objects:  31% (7/22)        
remote: Counting objects:  36% (8/22)        
remote: Counting objects:  40% (9/22)        
remote: Counting objects:  45% (10/22)        
remote: Counting objects:  50% (11/22)        
remote: Counting objects:  54% (12/22)        
remote: Counting objects:  59% (13/22)        
remote: Counting objects:  63% (14/22)        
remote: Counting objects:  68% (15/22)        
remote: Counting objects:  72% (16/22)        
remote: Counting objects:  77% (17/22)        
remote: Counting objects:  81% (18/22)        
remote: Counting objects:  86% (19/22)        
remote: Counting objects:  90% (20/22)        
remote: Counting objects:  95% (21/22)        
remote: Counting objects: 100% (22/22)        
remote: Counting objects: 100% (22/22), done.        
remote: Compressing objects:  11% (1/9)        
remote: Compressing objects:  22% (2/9)        
remote: Compressing objects:  33% (3/9)        
remote: Compressing objects:  44% (4/9)        
remote: Compressing objects:  55% (5/9)        
remote: Compressing objects:  66% (6/9)        
remote: Compressing objects:  77% (7/9)        
remote: Compressing objects:  88% (8/9)        
remote: Compressing objects: 100% (9/9)        
remote: Compressing objects: 100% (9/9), done.        
remote: Total 12 (delta 10), reused 3 (delta 3), pack-reused 0        
From https://github.com/python/cpython
 * branch                  master     -> FETCH_HEAD
Reset branch 'master'

test_ossaudiodev skipped -- [Errno 2] No such file or directory: '/dev/dsp'
test_winreg skipped -- No module named 'winreg'
Warning -- threading_cleanup() failed to cleanup 2 threads (count: 2, dangling: 3)
Warning -- Dangling thread: <Thread(Thread-4 (removeTarget), started daemon 4396862667024)>
Warning -- Dangling thread: <Thread(Thread-11 (removeTarget), started daemon 4396595259664)>
Warning -- Dangling thread: <_MainThread(MainThread, started 4396920310576)>
test_flat (test.test_logging.BuiltinLevelsTest) ... ok
test_issue27935 (test.test_logging.BuiltinLevelsTest) ... ok
test_nested_explicit (test.test_logging.BuiltinLevelsTest) ... ok
test_nested_inherited (test.test_logging.BuiltinLevelsTest) ... ok
test_nested_with_virtual_parent (test.test_logging.BuiltinLevelsTest) ... ok
test_regression_22386 (test.test_logging.BuiltinLevelsTest)
See issue #22386 for more information. ... ok
test_regression_29220 (test.test_logging.BuiltinLevelsTest)
See issue #29220 for more information. ... ok
test_callable_filter (test.test_logging.BasicFilterTest) ... ok
test_empty_filter (test.test_logging.BasicFilterTest) ... ok
test_filter (test.test_logging.BasicFilterTest) ... ok
test_handler_filter (test.test_logging.CustomLevelsAndFiltersTest) ... ok
test_logger_filter (test.test_logging.CustomLevelsAndFiltersTest) ... ok
test_specific_filters (test.test_logging.CustomLevelsAndFiltersTest) ... ok
test_builtin_handlers (test.test_logging.HandlerTest) ... ok
test_name (test.test_logging.HandlerTest) ... ok
test_path_objects (test.test_logging.HandlerTest)
Test that Path objects are accepted as filename arguments to handlers. ... ok
test_post_fork_child_no_deadlock (test.test_logging.HandlerTest)
Ensure child logging locks are not held; [bpo-6721](https://bugs.python.org/issue6721) & [bpo-36533](https://bugs.python.org/issue36533). ... ok
test_race (test.test_logging.HandlerTest) ... ok
test_flush (test.test_logging.MemoryHandlerTest) ... ok
test_flush_on_close (test.test_logging.MemoryHandlerTest)
Test that the flush-on-close configuration works as expected. ... ok
test_race_between_set_target_and_flush (test.test_logging.MemoryHandlerTest) ... ok
test_config0_ok (test.test_logging.ConfigFileTest) ... ok
test_config0_using_cp_ok (test.test_logging.ConfigFileTest) ... ok
test_config1_ok (test.test_logging.ConfigFileTest) ... ok
test_config2_failure (test.test_logging.ConfigFileTest) ... ok
test_config3_failure (test.test_logging.ConfigFileTest) ... ok
test_config4_ok (test.test_logging.ConfigFileTest) ... ok
test_config5_ok (test.test_logging.ConfigFileTest) ... ok
test_config6_ok (test.test_logging.ConfigFileTest) ... ok
test_config7_ok (test.test_logging.ConfigFileTest) ... ok
test_config8_ok (test.test_logging.ConfigFileTest) ... ok
test_config_set_handler_names (test.test_logging.ConfigFileTest) ... ok
test_defaults_do_no_interpolation (test.test_logging.ConfigFileTest)
[bpo-33802](https://bugs.python.org/issue33802) defaults should not get interpolated ... ok
test_logger_disabling (test.test_logging.ConfigFileTest) ... ok
test_noserver (test.test_logging.SocketHandlerTest) ... ok
test_output (test.test_logging.SocketHandlerTest) ... ok
test_output (test.test_logging.DatagramHandlerTest) ... ok
test_persistent_loggers (test.test_logging.MemoryTest) ... ok
test_encoding_cyrillic_unicode (test.test_logging.EncodingTest) ... ok
test_encoding_plain_file (test.test_logging.EncodingTest) ... ok
test_warnings (test.test_logging.WarningsTest) ... ok
test_warnings_no_handlers (test.test_logging.WarningsTest) ... ok
test_baseconfig (test.test_logging.ConfigDictTest) ... ok
test_config0_ok (test.test_logging.ConfigDictTest) ... ok
test_config11_ok (test.test_logging.ConfigDictTest) ... ok
test_config12_failure (test.test_logging.ConfigDictTest) ... ok
test_config13_failure (test.test_logging.ConfigDictTest) ... ok
test_config14_ok (test.test_logging.ConfigDictTest) ... ok
test_config15_ok (test.test_logging.ConfigDictTest) ... ok
test_config1_ok (test.test_logging.ConfigDictTest) ... ok
test_config2_failure (test.test_logging.ConfigDictTest) ... ok
test_config2a_failure (test.test_logging.ConfigDictTest) ... ok
test_config2b_failure (test.test_logging.ConfigDictTest) ... ok
test_config3_failure (test.test_logging.ConfigDictTest) ... ok
test_config4_ok (test.test_logging.ConfigDictTest) ... ok
test_config4a_ok (test.test_logging.ConfigDictTest) ... ok
test_config5_ok (test.test_logging.ConfigDictTest) ... ok
test_config6_failure (test.test_logging.ConfigDictTest) ... ok
test_config7_ok (test.test_logging.ConfigDictTest) ... ok
test_config_10_ok (test.test_logging.ConfigDictTest) ... ok
test_config_8_ok (test.test_logging.ConfigDictTest) ... ok
test_config_8a_ok (test.test_logging.ConfigDictTest) ... ok
test_config_9_ok (test.test_logging.ConfigDictTest) ... ok
test_custom_formatter_class_with_validate (test.test_logging.ConfigDictTest) ... ok
test_custom_formatter_class_with_validate2 (test.test_logging.ConfigDictTest) ... ok
test_custom_formatter_class_with_validate2_with_wrong_fmt (test.test_logging.ConfigDictTest) ... ok
test_custom_formatter_class_with_validate3 (test.test_logging.ConfigDictTest) ... ok
test_custom_formatter_function_with_validate (test.test_logging.ConfigDictTest) ... ok
test_listen_config_10_ok (test.test_logging.ConfigDictTest) ... ok
test_listen_config_1_ok (test.test_logging.ConfigDictTest) ... ok
test_listen_verify (test.test_logging.ConfigDictTest) ... ok
test_namedtuple (test.test_logging.ConfigDictTest) ... ok
test_out_of_order (test.test_logging.ConfigDictTest) ... ok
test_out_of_order_with_dollar_style (test.test_logging.ConfigDictTest) ... ok
test_manager_loggerclass (test.test_logging.ManagerTest) ... ok
test_set_log_record_factory (test.test_logging.ManagerTest) ... ok
test_braces (test.test_logging.FormatterTest) ... ok
test_default_msec_format_none (test.test_logging.FormatterTest) ... ok
test_defaults_parameter (test.test_logging.FormatterTest) ... ok
test_dollars (test.test_logging.FormatterTest) ... ok
test_format_validate (test.test_logging.FormatterTest) ... ok
test_invalid_style (test.test_logging.FormatterTest) ... ok
test_percent (test.test_logging.FormatterTest) ... ok
test_time (test.test_logging.FormatterTest) ... ok
test_custom (test.test_logging.BufferingFormatterTest) ... ok
test_default (test.test_logging.BufferingFormatterTest) ... ok
test_can_represent_stream_with_int_name (test.test_logging.StreamHandlerTest) ... ok
test_error_handling (test.test_logging.StreamHandlerTest) ... ok
test_stream_setting (test.test_logging.StreamHandlerTest)
Test setting the handler's stream ... ok
test_logrecord_class (test.test_logging.LogRecordFactoryTest) ... ok
test_child_loggers (test.test_logging.ChildLoggerTest) ... ok
test_formatting (test.test_logging.QueueHandlerTest) ... ok
test_queue_handler (test.test_logging.QueueHandlerTest) ... ok
test_queue_listener (test.test_logging.QueueHandlerTest) ... ok
test_queue_listener_with_StreamHandler (test.test_logging.QueueHandlerTest) ... ok
test_queue_listener_with_multiple_handlers (test.test_logging.QueueHandlerTest) ... ok
test_no_failure (test.test_logging.ShutdownTest) ... ok
test_with_ioerror_in_acquire (test.test_logging.ShutdownTest) ... ok
test_with_ioerror_in_close (test.test_logging.ShutdownTest) ... ok
test_with_ioerror_in_flush (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_acquire_with_raise (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_acquire_without_raise (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_close_with_raise (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_close_without_raise (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_flush_with_raise (test.test_logging.ShutdownTest) ... ok
test_with_other_error_in_flush_without_raise (test.test_logging.ShutdownTest) ... ok
test_with_valueerror_in_acquire (test.test_logging.ShutdownTest) ... ok
test_with_valueerror_in_close (test.test_logging.ShutdownTest) ... ok
test_with_valueerror_in_flush (test.test_logging.ShutdownTest) ... ok
test_critical (test.test_logging.ModuleLevelMiscTest) ... ok
test_debug (test.test_logging.ModuleLevelMiscTest) ... ok
test_disable (test.test_logging.ModuleLevelMiscTest) ... ok
test_error (test.test_logging.ModuleLevelMiscTest) ... ok
test_info (test.test_logging.ModuleLevelMiscTest) ... ok
test_log (test.test_logging.ModuleLevelMiscTest) ... ok
test_logging_at_shutdown (test.test_logging.ModuleLevelMiscTest) ... ok
test_recursion_error (test.test_logging.ModuleLevelMiscTest) ... ok
test_set_logger_class (test.test_logging.ModuleLevelMiscTest) ... ok
test_subclass_logger_cache (test.test_logging.ModuleLevelMiscTest) ... ok
test_warning (test.test_logging.ModuleLevelMiscTest) ... ok
test_critical (test.test_logging.BasicConfigTest) ... ok
test_datefmt (test.test_logging.BasicConfigTest) ... ok
test_debug (test.test_logging.BasicConfigTest) ... ok
test_encoding (test.test_logging.BasicConfigTest) ... ok
test_encoding_errors (test.test_logging.BasicConfigTest) ... ok
test_encoding_errors_default (test.test_logging.BasicConfigTest) ... ok
test_encoding_errors_none (test.test_logging.BasicConfigTest) ... ok
test_error (test.test_logging.BasicConfigTest) ... ok
test_filemode (test.test_logging.BasicConfigTest) ... ok
test_filename (test.test_logging.BasicConfigTest) ... ok
test_force (test.test_logging.BasicConfigTest) ... ok
test_format (test.test_logging.BasicConfigTest) ... ok
test_handlers (test.test_logging.BasicConfigTest) ... ok
test_incompatible (test.test_logging.BasicConfigTest) ... ok
test_info (test.test_logging.BasicConfigTest) ... ok
test_level (test.test_logging.BasicConfigTest) ... ok
test_log (test.test_logging.BasicConfigTest) ... ok
test_no_kwargs (test.test_logging.BasicConfigTest) ... ok
test_stream (test.test_logging.BasicConfigTest) ... ok
test_strformatstyle (test.test_logging.BasicConfigTest) ... ok
test_stringtemplatestyle (test.test_logging.BasicConfigTest) ... ok
test_style (test.test_logging.BasicConfigTest) ... ok
test_warning (test.test_logging.BasicConfigTest) ... ok
test_critical (test.test_logging.LoggerAdapterTest) ... ok
test_exception (test.test_logging.LoggerAdapterTest) ... ok
test_exception_excinfo (test.test_logging.LoggerAdapterTest) ... ok
test_has_handlers (test.test_logging.LoggerAdapterTest) ... ok
test_is_enabled_for (test.test_logging.LoggerAdapterTest) ... ok
test_nested (test.test_logging.LoggerAdapterTest) ... ok
test_caching (test.test_logging.LoggerTest) ... ok
test_exception (test.test_logging.LoggerTest) ... ok
test_find_caller_with_stack_info (test.test_logging.LoggerTest) ... ok
test_find_caller_with_stacklevel (test.test_logging.LoggerTest) ... ok
test_has_handlers (test.test_logging.LoggerTest) ... ok
test_has_handlers_no_propagate (test.test_logging.LoggerTest) ... ok
test_invalid_names (test.test_logging.LoggerTest) ... ok
test_is_enabled_for (test.test_logging.LoggerTest) ... ok
test_is_enabled_for_disabled_logger (test.test_logging.LoggerTest) ... ok
test_log_invalid_level_no_raise (test.test_logging.LoggerTest) ... ok
test_log_invalid_level_with_raise (test.test_logging.LoggerTest) ... ok
test_make_record_with_extra_no_overwrite (test.test_logging.LoggerTest) ... ok
test_make_record_with_extra_overwrite (test.test_logging.LoggerTest) ... ok
test_pickling (test.test_logging.LoggerTest) ... ok
test_root_logger_aliases (test.test_logging.LoggerTest) ... ok
test_set_invalid_level (test.test_logging.LoggerTest) ... ok
test_basic (test.test_logging.SMTPHandlerTest) ... ok
test_delay (test.test_logging.FileHandlerTest) ... ok
test_file_created (test.test_logging.RotatingFileHandlerTest) ... ok
test_namer_rotator_inheritance (test.test_logging.RotatingFileHandlerTest) ... ok
test_rollover_filenames (test.test_logging.RotatingFileHandlerTest) ... ok
test_rotator (test.test_logging.RotatingFileHandlerTest) ... ok
test_should_not_rollover (test.test_logging.RotatingFileHandlerTest) ... ok
test_should_rollover (test.test_logging.RotatingFileHandlerTest) ... ok
test_last_resort (test.test_logging.LastResortTest) ... ok
test_dict_arg (test.test_logging.LogRecordTest) ... ok
test_multiprocessing (test.test_logging.LogRecordTest) ... ok
test_optional (test.test_logging.LogRecordTest) ... ok
test_str_rep (test.test_logging.LogRecordTest) ... ok
test_formatting (test.test_logging.ExceptionTest) ... ok
test_output (test.test_logging.SysLogHandlerTest) ... ok
test_output (test.test_logging.IPv6SysLogHandlerTest) ... ok
test_output (test.test_logging.HTTPHandlerTest) ... ok
test_basic (test.test_logging.NTEventLogHandlerTest) ... skipped 'win32evtlog/win32evtlogutil/pywintypes required for this test.'
test_compute_rollover_D (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_H (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_M (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_MIDNIGHT (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_S (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_W0 (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_daily_attime (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_compute_rollover_weekly_attime (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_invalid (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_rollover (test.test_logging.TimedRotatingFileHandlerTest) ... ok
test_noserver (test.test_logging.UnixSocketHandlerTest) ... ok
test_output (test.test_logging.UnixSocketHandlerTest) ... ok
test_output (test.test_logging.UnixDatagramHandlerTest) ... ok
test_output (test.test_logging.UnixSysLogHandlerTest) ... ok
test__all__ (test.test_logging.MiscTestCase) ... ok
test_calls_task_done_after_stop (test.test_logging.QueueListenerTest) ... ok
test_handle_called_with_mp_queue (test.test_logging.QueueListenerTest) ... ok
test_handle_called_with_queue_queue (test.test_logging.QueueListenerTest) ... ok
test_no_messages_in_queue_after_stop (test.test_logging.QueueListenerTest)
Five messages are logged then the QueueListener is stopped. This ... ok

----------------------------------------------------------------------

Ran 202 tests in 24.409s

OK (skipped=1)
test_tix skipped -- Tk unavailable due to TclError: no display name and no $DISPLAY environment variab [...]
test_ttk_guionly skipped -- Tk unavailable due to TclError: no display name and no $DISPLAY environment variab [...]
test_winconsoleio skipped -- test only relevant on win32
test_devpoll skipped -- test works only on Solaris OS family
test_flock (__main__.FNTLEINTRTest) ... ok
test_lockf (__main__.FNTLEINTRTest) ... ok
test_read (__main__.OSEINTRTest) ... ok
test_wait (__main__.OSEINTRTest) ... ok
test_wait3 (__main__.OSEINTRTest) ... ok
test_wait4 (__main__.OSEINTRTest) ... ok
test_waitpid (__main__.OSEINTRTest) ... ok
test_write (__main__.OSEINTRTest) ... ok
test_devpoll (__main__.SelectEINTRTest) ... skipped 'need select.devpoll'
test_epoll (__main__.SelectEINTRTest) ... ok
test_kqueue (__main__.SelectEINTRTest) ... skipped 'need select.kqueue'
test_poll (__main__.SelectEINTRTest) ... ok
test_select (__main__.SelectEINTRTest) ... ok
test_sigtimedwait (__main__.SignalEINTRTest) ... ok
test_sigwaitinfo (__main__.SignalEINTRTest) ... ok
test_accept (__main__.SocketEINTRTest) ... ok
test_open (__main__.SocketEINTRTest) ... ok
test_os_open (__main__.SocketEINTRTest) ... ok
test_recv (__main__.SocketEINTRTest) ... ok
test_recvmsg (__main__.SocketEINTRTest) ... ok
test_send (__main__.SocketEINTRTest) ... ok
test_sendall (__main__.SocketEINTRTest) ... ok
test_sendmsg (__main__.SocketEINTRTest) ... ok
test_sleep (__main__.TimeEINTRTest) ... ok

----------------------------------------------------------------------
Ran 24 tests in 6.787s

OK (skipped=2)
test_winsound skipped -- No module named 'winsound'
test_kqueue skipped -- test works only on BSD
test_msilib skipped -- No module named '_msi'
test_zipfile64 skipped -- test requires loads of disk-space bytes and a long time to run
test_ioctl skipped -- Unable to open /dev/tty
test_nis skipped -- No module named 'nis'
test_startfile skipped -- object <module 'os' from '/home/dje/cpython-buildarea/3.x.edelsohn-rhel8-z/build/Lib/os.py'> has no attribute 'startfile'
test_tk skipped -- Tk unavailable due to TclError: no display name and no $DISPLAY environment variab [...]
<string>:2: PendingDeprecationWarning: lib2to3 package is deprecated and may not be able to parse Python 3.10+
make: *** [Makefile:1199: buildbottest] Error 3

@@ -8779,6 +8782,14 @@ void
_Py_closerange(int first, int last)
{
first = Py_MAX(first, 0);
#ifdef HAVE_CLOSE_RANGE
if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nicer to cache ENOSYS the first time we try close_range and avoid it in future _Py_closerange calls — assuming this is ever used more than once per process, which might not be true.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented such cache in the PEP 446 implementation: remind if a syscall supports atomic "O_CLOEXEC" flag. See for example _Py_open_cloexec_works in Python/fileutils.c.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, I don't think this code path is sensitive enough to really care.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, nice, I hadn't thought of caching that. good idea. (one less failed syscall attempt before the real work likely involving many syscalls gets done in this case; so not a huge deal but still worthwhile)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the subprocess use case, the cache will likely only be first initialized in child processes, each child process has to do the check, and so the cache is useless.

I would mostly benefit to os.closerange().

I'm fine with not adding a cache. I agree that os.closerange() is an uncommon function.

xzy3 pushed a commit to xzy3/cpython that referenced this pull request Oct 18, 2020
)

close_range(2) should be preferred at all times if it's available, otherwise we'll use closefrom(2) if available with a fallback to fdwalk(3) or plain old loop over fd range in order of most efficient to least.

[note that this version does check for ENOSYS, but currently ignores all other errors]

Automerge-Triggered-By: @pablogsal
adorilson pushed a commit to adorilson/cpython that referenced this pull request Mar 13, 2021
)

close_range(2) should be preferred at all times if it's available, otherwise we'll use closefrom(2) if available with a fallback to fdwalk(3) or plain old loop over fd range in order of most efficient to least.

[note that this version does check for ENOSYS, but currently ignores all other errors]

Automerge-Triggered-By: @pablogsal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants