Message389605
That's what happened. Function foo creates a reference loop. It has reference to the module dict, and the dict has reference to the function. The dict has also references to BytesIO and ZipFile objects. At shutdown stage the garbage collector is called. It founds the reference loop which contains the module dict, function foo and BytesIO and ZipFile objects. It tries to break the loop by calling the destructor of arbitrary object in the loop. In that case it is the BytesIO object. It does not help, but finally the destructor of the ZipFile object is called (either directly or after breaking the loop and destroying the module dict). The ZipFile destructor tries to close the BytesIO object, but it is already closed in its destructor.
It is a dangerous situation which potentially can cause data corruption (if the underlying stream is closed before flushing buffers). Clearing the module dict before invoking garbage collecting would solve this issue. Making the garbage collector more clever and and avoid destroying objects if it does not break the loop would help too, but it is more complex problem and such change could not be backported to 3.8.
Victor, were there any changes in the garbage collector or interpreter shutdown code in 3.8? |
|
Date |
User |
Action |
Args |
2021-03-27 15:28:19 | serhiy.storchaka | set | recipients:
+ serhiy.storchaka, pitrou, vstinner, joernheissler, xtreak |
2021-03-27 15:28:19 | serhiy.storchaka | set | messageid: <1616858899.46.0.221172447213.issue37773@roundup.psfhosted.org> |
2021-03-27 15:28:19 | serhiy.storchaka | link | issue37773 messages |
2021-03-27 15:28:18 | serhiy.storchaka | create | |
|