# HG changeset patch # User Manuel Jacob <m...@manueljacob.de> # Date 1653434314 -7200 # Wed May 25 01:18:34 2022 +0200 # Branch stable # Node ID a9e51487cb9a73f871daf0d43a2b6eec9adadbbd # Parent d058898bdd462b03c5bff38ad40d1f855ea51c23 # EXP-Topic worker-pickle-load-EINTR worker: prevent cPickle from directly interacting with C FILEs
diff --git a/mercurial/worker.py b/mercurial/worker.py --- a/mercurial/worker.py +++ b/mercurial/worker.py @@ -100,6 +100,8 @@ del buf[pos:] return bytes(buf) + _picklereader = _blockingreader + else: @@ -111,6 +113,24 @@ def _blockingreader(wrapped): return wrapped + # The following hack is needed to prevent cPickle from using its buggy fast + # path for directly interacting with C FILEs. Instead, the file object + # should interact with C FILEs. For that, we need to make cPickle think + # that we did not actually pass a file object. + # CPickle's interaction with FILEs has at least the following two problems: + # 1) CPickle does not retry operations on EINTR, while file objects do. + # 2) CPickle does not check if an error (e.g. EINTR) happened during + # getc(). Instead, it thinks that EOF was reached. + + class _passthrough(object): + def __init__(self, wrapped): + self._wrapped = wrapped + + def __getattr__(self, name): + return getattr(self._wrapped, name) + + _picklereader = _passthrough + if pycompat.isposix or pycompat.iswindows: _STARTUP_COST = 0.01 @@ -292,7 +312,7 @@ while openpipes > 0: for key, events in selector.select(): try: - res = util.pickle.load(_blockingreader(key.fileobj)) + res = util.pickle.load(_picklereader(key.fileobj)) if hasretval and res[0]: retval.update(res[1]) else: _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel