<!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>