New submission from Gabriel C <gabri...@mit.edu>:

The following results in a segfault on 3.7.4 (running on macOS high sierra) and 
3.5 (running on ubuntu 16.04). It does not happen in python 2.7.

The problem seems to involve two effects. The first is the creation of a class 
with a dynamic type that inherits from a MemoryError (but any exception will 
work). The second is pickling an instance of that MemoryError (note that the 
dynamic type is never pickled).

If a basic (non-exception) class is used instead of the MemoryError (see 
uncomment case 1), then the segfault does not occur in my testing. If the 
exception being pickled is a different type to the one used as the base class 
for the dynamic type, the segfault does not occur. 

Note that unpickling the MemoryError actually raises another exception, this 
raised exception (see uncomment case 2) is raised by the dynamic type class 
__init__ method. It seems that in trying to unpickle the MemoryError, pickle 
attempts to create an instance of the unrelated dynamic type instead. Examining 
the stack trace (uncomment case 3), shows the raised exception is indeed 
originating from attempting to unpickle the MemoryError.

The segfault does not happen immediately, but instead after several attempts. 
It can happen after as few as 5 attempts or as many as 100. 

```
import pickle

def CreateDynamicClass(basetype):
    class DynamicClassImpl(basetype):
        def __init__(self):
            super(DynamicClassImpl, self).__init__()

    return DynamicClassImpl()

class TestClass(object):
    pass

N_attemps = 1000

pickle_list = []

def load_list():
    for i in range(N_attemps):
        test_exception = MemoryError("Test" + str(i))
        #test_exception = TestClass() # Uncomment case 1
        pickle_list.append(pickle.dumps(test_exception))
load_list()

def unload_list():
    for i in range(N_attemps):
        try:
            test_object_instance = pickle.loads(pickle_list.pop())
            test_dynamic_object = CreateDynamicClass(MemoryError)
            #test_dynamic_object = CreateDynamicClass(TestClass) # Uncomment 
case 1
        except Exception as e:
            print("Exception at iteration {}: {}".format(i, e)) # Uncomment 
case 2
            #raise # Uncomment case 3
            pass
unload_list()
```

----------
components: Library (Lib)
messages: 350932
nosy: gabrielc
priority: normal
severity: normal
status: open
title: Segfault when using pickle with exceptions and dynamic class inheritance
type: crash
versions: Python 3.5, Python 3.7

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue37997>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to