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: