Forum Archive

Crash

mrJean1

Pythonista3 crashes on certain objects returned by gc.get_objects(). This only occurs with Python 3.5.1 but not with 2.7.12.

The culprit appears to be a 1-tuple containing a NULL item. Below is an example demonstrating the issue. Uncomment the # line to observe the crash.

import gc
for i, obj in enumerate(gc.get_objects()):
    t = repr(obj)
    if 'NULL' in t and isinstance(obj, tuple):
        print(i, t)
#       print('...', obj[0])  # crashes
print(i, 'total')

dgelessus

I can't reproduce this - on my iPhone SE (64-bit, iOS 10.3.3, Pythonista beta build 311008) this code doesn't find a tuple containing an actual NULL. (The only tuple found is ('NULL', None), which is the co_consts tuple of the currently executing code.)

If you're able to reproduce this, can you have a look at the bad tuple's referrers (gc.get_referrers)? That might give you a hint about what could have created that tuple.

Phuket2

@mrJean1 , i am a nubie. But I tried different variations of what you posted. But it seems to me if you replace 'NULL' with 'null' you get the desired result. My reasoning to try 'null' is just because I know that is what json uses.
Sorry, if I am way of base. I just tried

mrJean1

After modifying the sample to show the referrers:

import gc
gc.collect()
for i, obj in enumerate(gc.get_objects()):
    t = repr(obj)
    if '<NULL>' in t and isinstance(obj, tuple):
        for j, ref in enumerate(gc.get_referrers(obj)):
            print('ref', j, type(ref), ref, end='\n\n')
        print('refs', j, 'total')
        print(i, t)
# crash print('...', obj[0])
print(i, 'total')
import sys
print(sys.version)

The shortened Console output with Python 3.5.1 in Pythonista v. 3.1 (301016) is the following:

ref 0 <class 'list'> [{'__init__': <slot wrapper '__init__' of 'object' objects>, ..., ..., <frame object at 0x1099183e8>]   <<< very long list shortened <<<

ref 1 <class 'tuple'> (7595, (<NULL>,))

ref 2 <class 'dict'> {'i': 7595, 'j': 2, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x109969710>, '__cached__': None, '__spec__': None, 'obj': (<NULL>,), '__file__': '/private/var/mobile/Containers/Shared/AppGroup/A45067AD-96C3-483D-9A6E-F33AA6C0CBA5/Pythonista3/Documents/nullcrash.py', '__name__': '__main__', '__doc__': None, 'r': {...}, 't': '(<NULL>,)', '__builtins__': <module 'builtins' (built-in)>, 'gc': <module 'gc' (built-in)>}

refs 2 total
7595 (<NULL>,)
7602 total
3.5.1 (default, Sep 20 2016, 14:05:14)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)]
dgelessus

Ref 0 is almost certainly the gc.get_objects() list (that's the only reason I can think of why it would contain random stuff like object.__dict__ and a frame). Ref 1 is the tuple returned from the outer enumerate for the current iteration. Ref 2 is the __dict__ of the currently running script. None of these explain where the tuple would come from though... Do you have anything in your pythonista_startup that uses ctypes or objc_util perhaps? I don't see how else you could get a NULL pointer into a tuple.

mrJean1

This is the plain Pythonista 3.1 app with only one other thing installed, the Dropbox File Picker. Even after removing that and restarting, the 1-tuple exists. Btw, this is a 16 GB iPad Air 2 with 2+ GB of available storage running iOS 10.3.3.