Multiple calls to__del__ during object destruction¶
ID: py/multiple-calls-to-deleteKind: problemSecurity severity: Severity: warningPrecision: very-highTags: - quality - reliability - correctnessQuery suites: - python-security-and-quality.qls
Click to see the query in the CodeQL repository
Python, unlike some other object-oriented languages such as Java, allows the developer complete freedom in when and how superclass finalizers are called during object finalization. However, the developer has responsibility for ensuring that objects are properly cleaned up.
Objects with a__del__ method (a finalizer) often hold resources such as file handles that need to be cleaned up. If a superclass finalizer is called multiple times, this may lead to errors such as closing an already closed file, and lead to objects not being cleaned up properly as expected.
There are a number of ways that a__del__ method may be be called more than once.
There may be more than one explicit call to the method in the hierarchy of
__del__methods.In situations involving multiple inheritance, an finalization method may call the finalizers of each of its base types, which themselves both call the finalizer of a shared base type. (This is an example of the Diamond Inheritance problem)
Another situation involving multiple inheritance arises when a subclass calls the
__del__methods of each of its base classes, one of which callssuper().__del__. This super call resolves to the next class in the Method Resolution Order (MRO) of the subclass, which may be another base class that already has its initializer explicitly called.
Recommendation¶
Ensure that each finalizer method is called exactly once during finalization. This can be ensured by callingsuper().__del__ for each finalizer method in the inheritance chain.
Example¶
In the following example, there is a mixture of explicit calls to__del__ and calls usingsuper(), resulting inVehicle.__del__ being called twice.FixedSportsCar.__del__ fixes this by usingsuper() consistently with the other delete methods.
#Calling a method multiple times by using explicit calls when a base uses super()classVehicle(object):def__del__(self):recycle(self.base_parts)super(Vehicle,self).__del__()classCar(Vehicle):def__del__(self):recycle(self.car_parts)super(Car,self).__del__()classSportsCar(Car,Vehicle):# BAD: Vehicle.__del__ will get called twicedef__del__(self):recycle(self.sports_car_parts)Car.__del__(self)Vehicle.__del__(self)# GOOD: super() is used ensuring each del method is called once.classFixedSportsCar(Car,Vehicle):def__del__(self):recycle(self.sports_car_parts)super(SportsCar,self).__del__()
References¶
Python Reference:del.
Python Standard Library:super.
Python Glossary:Method resolution order.
Wikipedia:The Diamond Problem.