Mercurial > public > mercurial-scm > hg
comparison mercurial/util.py @ 48940:2974cdda819b
util: remove iterfile() variant for buggy EINTR handling
The workaround for Python 2 is no longer needed. So we can delete some
code.
Differential Revision: https://phab.mercurial-scm.org/D12346
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Thu, 03 Mar 2022 07:56:47 -0800 |
parents | f254fc73d956 |
children | 642e31cb55f0 |
comparison
equal
deleted
inserted
replaced
48939:37537a4d2695 | 48940:2974cdda819b |
---|---|
23 import io | 23 import io |
24 import itertools | 24 import itertools |
25 import locale | 25 import locale |
26 import mmap | 26 import mmap |
27 import os | 27 import os |
28 import platform as pyplatform | |
29 import re as remod | 28 import re as remod |
30 import shutil | 29 import shutil |
31 import stat | 30 import stat |
32 import sys | 31 import sys |
33 import time | 32 import time |
2903 else: | 2902 else: |
2904 tonativeeol = pycompat.identity | 2903 tonativeeol = pycompat.identity |
2905 fromnativeeol = pycompat.identity | 2904 fromnativeeol = pycompat.identity |
2906 nativeeolwriter = pycompat.identity | 2905 nativeeolwriter = pycompat.identity |
2907 | 2906 |
2908 if pyplatform.python_implementation() == b'CPython' and sys.version_info < ( | 2907 |
2909 3, | 2908 # TODO delete since workaround variant for Python 2 no longer needed. |
2910 0, | 2909 def iterfile(fp): |
2911 ): | 2910 return fp |
2912 # There is an issue in CPython that some IO methods do not handle EINTR | |
2913 # correctly. The following table shows what CPython version (and functions) | |
2914 # are affected (buggy: has the EINTR bug, okay: otherwise): | |
2915 # | |
2916 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0 | |
2917 # -------------------------------------------------- | |
2918 # fp.__iter__ | buggy | buggy | okay | |
2919 # fp.read* | buggy | okay [1] | okay | |
2920 # | |
2921 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo. | |
2922 # | |
2923 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods | |
2924 # like "read*" work fine, as we do not support Python < 2.7.4. | |
2925 # | |
2926 # Although we can workaround the EINTR issue for fp.__iter__, it is slower: | |
2927 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in | |
2928 # CPython 2, because CPython 2 maintains an internal readahead buffer for | |
2929 # fp.__iter__ but not other fp.read* methods. | |
2930 # | |
2931 # On modern systems like Linux, the "read" syscall cannot be interrupted | |
2932 # when reading "fast" files like on-disk files. So the EINTR issue only | |
2933 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG) | |
2934 # files approximately as "fast" files and use the fast (unsafe) code path, | |
2935 # to minimize the performance impact. | |
2936 | |
2937 def iterfile(fp): | |
2938 fastpath = True | |
2939 if type(fp) is file: | |
2940 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode) | |
2941 if fastpath: | |
2942 return fp | |
2943 else: | |
2944 # fp.readline deals with EINTR correctly, use it as a workaround. | |
2945 return iter(fp.readline, b'') | |
2946 | |
2947 | |
2948 else: | |
2949 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed. | |
2950 def iterfile(fp): | |
2951 return fp | |
2952 | 2911 |
2953 | 2912 |
2954 def iterlines(iterator): | 2913 def iterlines(iterator): |
2955 # type: (Iterator[bytes]) -> Iterator[bytes] | 2914 # type: (Iterator[bytes]) -> Iterator[bytes] |
2956 for chunk in iterator: | 2915 for chunk in iterator: |