pypy2 bug skipping finally
I found something that looks like a weird jit bug where a finally clause is completely skipped. It happens when running pypy3 untranslated tests on top of pypy2-c-jit (I am running a build from commit 1c274d79f388, likely this one), on the branch
py3.7-finally-bug. Here's how to reproduce the bug:
On the branch, run:
pypy test_all.py module/marshal/test/ -s
The effect is the following: The test fails because
codepoints_in_utf8('ab\xc3\x82\xc2\x84') gives the
wrong result! it returns 6, where 4 would be correct. This happens, because the
cast in this functions isn't working right, specifically this one:
Instead of turning
0xc3=195 into -61 it just returns 195.
Why does that happen? In
ll2ctypes.force_cast there is this line 1382:
if RESTYPE == TYPE1: return value
This branch is taken, despite the two types being
lltype.Signed. They compare equal.
Why do they compare equal?
LowLevelType.__eq__ does the following in line 182:
return self.__class__ is other.__class__ and ( self is other or safe_equal(self.__dict__, other.__dict__))
So we need to look at
safe_equal. That uses a dict that stores pairs of ids of
the compared dicts to check whether there is a recursive comparison going on:
seeingkey = (id(x), id(y)) if seeingkey in seeing: return True seeing[seeingkey] = True try: return x == y finally: del seeing[seeingkey]
There is no other call to safe_equal on the stack, however, the dict seeing is
still not empty! This means for some reason the finally was not executed at some
point. I confirmed this fact by adding debug prints before and after the call to
safe_equal, and they show that at some point the dict grows to size one but then doesn't shrink to 0 again.
Currently I am stuck, I didn't manage to track down further what is happening. The generated traces for
safe_equal look reasonable and I haven't managed to reduce the test case to a somewhat smaller one either