<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=utf-8" http-equiv=Content-Type>
<STYLE type=text/css>
BLOCKQUOTE{margin-Top: 0px; margin-Bottom: 0px; margin-Left: 2em}
</STYLE>
<META name=GENERATOR content="MSHTML 11.00.10570.1001"><!-- flashmail style begin -->
<STYLE type=text/css>
body {border-width:0;margin:0}
img {border:0;margin:0;padding:0}
</STYLE>
<BASE target=_blank><!-- flashmail style end --></HEAD>
<BODY
style="BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 10.5pt; FONT-FAMILY: 微软雅黑; BORDER-RIGHT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; COLOR: #000000; MARGIN: 12px; LINE-HEIGHT: 1.5; BORDER-TOP-WIDTH: 0px"
marginheight="0" marginwidth="0">
<DIV>This problem is caused by caching GeneratorExit exception:</DIV>
<DIV> </DIV>
<DIV><A
href="https://bitbucket.org/pypy/pypy/src/8b43b50fbf61f46701d398bf514cf540201ffd03/pypy/interpreter/generator.py?at=py3.5&fileviewer=file-view-default#generator.py-454:457">https://bitbucket.org/pypy/pypy/src/8b43b50fbf61f46701d398bf514cf540201ffd03/pypy/interpreter/generator.py?at=py3.5&fileviewer=file-view-default#generator.py-454:457</A></DIV>
<DIV> </DIV>
<DIV>In Python 3, an exception saves its traceback in __traceback__ attribute.
When an exception object with __traceback__ is raised again, current
frame is appended to the __traceback__. When the GeneratorExit is raised inside
a iterator, the __traceback__ attribute of this object saves the frame, which
prevents the iterator from been collected by GC.</DIV>
<DIV> </DIV>
<DIV>Since __traceback__ attribute is mutable, it is generally a dangerous idea
to reuse an exception object in Python 3, the problem includes: creating memory
leaks with frames, wrong traceback, etc. I think remove the caching will solve
the problem.</DIV>
<DIV> </DIV>
<DIV>It's quite easy to be validated with the following script:</DIV>
<DIV> </DIV>
<DIV style="FONT-FAMILY: Courier New">def
test():<BR> try:<BR>
yield 1<BR> except BaseException as
e:<BR> global
ex<BR> ex = e</DIV>
<DIV style="FONT-FAMILY: Courier New"> </DIV>
<DIV style="FONT-FAMILY: Courier New">for _ in range(10):<BR>
t = test()<BR> next(t)<BR> t.close()</DIV>
<DIV style="FONT-FAMILY: Courier New"> </DIV>
<DIV style="FONT-FAMILY: Courier New">import traceback</DIV>
<DIV style="FONT-FAMILY: Courier New">traceback.print_tb(ex.__traceback__)</DIV>
<DIV> </DIV>
<DIV>You will see many frames in the traceback.</DIV>
<DIV> </DIV>
<DIV>Removing the __traceback__ attribute before each usage is not acceptable,
because the exception may be used concurrently in different threads,
or nested in a finalizer when GC is triggered inside the generator close.</DIV>
<DIV> </DIV>
<DIV style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana; COLOR: #c0c0c0"
align=left>2018-06-28
<HR id=SignNameHR
style="BORDER-TOP: #c0c0c0 1px solid; HEIGHT: 1px; BORDER-RIGHT: 0px; WIDTH: 122px; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px"
align=left>
<SPAN id=_FlashSignName>hubo</SPAN> </DIV>
<HR
style="BORDER-TOP: #c0c0c0 1px solid; HEIGHT: 1px; BORDER-RIGHT: 0px; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px">
<BLOCKQUOTE id=ntes-flashmail-quote
style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana; PADDING-LEFT: 0px; MARGIN-LEFT: 0px">
<DIV><STRONG>å‘件人:</STRONG>"hubo" <hubo@jiedaibao.com></DIV>
<DIV><STRONG>å‘é€æ—¶é—´ï¼š</STRONG>2018-06-28 13:06</DIV>
<DIV><STRONG>主题:</STRONG>[pypy-dev] Memory leaking with iterator.close() in
PyPy3</DIV>
<DIV><STRONG>收件人:</STRONG>"PyPy Developer Mailing
List"<pypy-dev@python.org></DIV>
<DIV><STRONG>抄é€ï¼š</STRONG></DIV>
<DIV> </DIV>
<DIV><STATIONERY>
<DIV>In PyPy3, when an iterator is closed with "close()" method, the
iterator leaks and cannot be collected.</DIV>
<DIV> </DIV>
<DIV>Execute the following script in PyPy3, the memory usage is increasing
very fast, and gc.collect() cannot collect the memory</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV style="FONT-FAMILY: Courier New">def test():</DIV>
<DIV style="FONT-FAMILY: Courier New"> yield 1</DIV>
<DIV style="FONT-FAMILY: Courier New"> </DIV>
<DIV style="FONT-FAMILY: Courier New">while True:</DIV>
<DIV style="FONT-FAMILY: Courier New"> t = test()</DIV>
<DIV style="FONT-FAMILY: Courier New"> t.close()</DIV>
<DIV style="FONT-FAMILY: Courier New"> </DIV>
<DIV><FONT face="Courier New"><SPAN
style="FONT-FAMILY: 微软雅黑"></SPAN></FONT> </DIV>
<DIV>The tested version:</DIV>
<DIV> </DIV>
<DIV>Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:10:04)<BR>[PyPy 6.0.0 with
GCC 6.2.0 20160901]</DIV>
<DIV> </DIV>
<DIV>This is not reproduced in CPython 3.5 and PyPy2.</DIV>
<DIV> </DIV>
<DIV style="FONT-SIZE: 10pt; FONT-FAMILY: Verdana; COLOR: #c0c0c0">
<DIV align=left>2018-06-28</DIV>
<HR id=SignNameHR
style="BORDER-TOP: #c0c0c0 1px solid; HEIGHT: 1px; BORDER-RIGHT: 0px; WIDTH: 122px; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px"
align=left>
<SPAN id=_FlashSignName>hubo</SPAN>
</DIV></STATIONERY></DIV></BLOCKQUOTE></BODY></HTML>