[PATCH 2 of 2 stable] worker: prevent cPickle from directly interacting with C FILEs
Manuel Jacob
me at manueljacob.de
Wed May 25 00:30:30 UTC 2022
# HG changeset patch
# User Manuel Jacob <me at 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:
More information about the Mercurial-devel
mailing list