Bug #10483
memory leak in BufferManager.openBuffers
70%
Related issues
History
#2 Updated by Constantin Asofiei 11 months ago
In BufferManager.bufferInitialized, the buffer.activeScopeDepth is 0-based; this code:
if (global)
{
...
}
else
{
int scopes = getOpenBufferScopes();
if (buffer.activeScopeDepth <= scopes)
{
openBuffers.addAt(scopes - buffer.activeScopeDepth, buffer);
buffer.addOpenBuffersScope(buffer.activeScopeDepth);
}
}
In the case where I see this, the 'activeScopeDepth' is from a dataset parameter, TemporaryBuffer.associateImpl ~line 2648:
// open scope for this new buffer. Bound buffers go to global scope, the other local
tbuf.openScopeAt(bind ? 0 : tbuf.bufferManager.getOpenBufferScopes() - 1);
Things are confusing is wrong with the meaning of 'depth'. For TemporaryBuffer.openScopeAt:
* @param blockDepth
* Zero-based depth of the block (starting from the outermost scope) at which the
* buffer scope is opened.
seems to be the depth of the stack, from the bottom (0 is the bottom of the stack). So using
tbuf.bufferManager.getOpenBufferScopes() - 1 for 'current scope' is right.
For ScopedList.addAt:
* Add the given element to the tail of the scope at the given scope depth, where zero depth
* represents the current scope, and a positive depth indicate older scopes. A depth of
* {@code scopes() - 1} indicates the global scope.
*
* @param depth
* Depth of the scope to which to add the element, as described above.
depth meaning is reversed: a zero means current scope, while scopes() - 1 the global scope.
So I think the code in bufferInitilized needs to be this:
int scopes = getOpenBufferScopes();
if (buffer.activeScopeDepth + 1 <= scopes)
{
openBuffers.addAt(scopes - (buffer.activeScopeDepth + 1), buffer);
buffer.addOpenBuffersScope(buffer.activeScopeDepth);
}
as we need to transform from a
0 to scopes' depth (for the activeScopeDepth) to a 'scopes - 1' to zero depth, as we need 0 to be 'current scope'.#3 Updated by Constantin Asofiei 11 months ago
- % Done changed from 0 to 70
- Assignee set to Constantin Asofiei
- Status changed from New to Review
- reviewer Alexandru Lungu, Greg Shah added
Actually, the memory leak was from a case where a buffer from a super-class is opened (in the pseudo-execute method for converted .cls) both in the super-class and child class. This ended up messing the openBuffers list for the current scope, as a buffer's scope must be opened only once in the current scope.
- Ensure a buffer is opened only once for the pseudo-execute calls for a type hierarchy in a converted .cls.
Eric - please also take a look. I've added a SEVERE logging in ScopedList if the same entry is added again in the scope. Maybe also log the stacktrace?
What is posted in #10483-2 still remains confusing for me.
#4 Updated by Greg Shah 11 months ago
Code Review Task Branch 10483a Revision 16137 and 16138
For RB.openScope(), what are 4GL code examples that cause a single buffer instance to ever have an open count > 0? I understand that your change is safer because of the conditions, but it seems like our approach should protect against any way that the same buffer instance can be opened more than once.
#5 Updated by Constantin Asofiei 11 months ago
Greg Shah wrote:
Code Review Task Branch 10483a Revision 16137 and 16138
For
RB.openScope(), what are 4GL code examples that cause a single buffer instance to ever have an open count> 0? I understand that your change is safer because of the conditions, but it seems like our approach should protect against any way that the same buffer instance can be opened more than once.
The change prevents the same buffer instance to open the scope more than once in the same 'execute'/external block. I agree that this should be somewhere lower in RB.openScope, and maybe consider any kind of block, to prevent this problem. Or maybe even ScopedList, if the key already exists, things get... weird with the linked nodes.
oo/Foo.clsclass oo.Foo inherits oo.Bar: method public void m1(). find first tt1. end. end.oo/Bar.clsclass oo.Bar: def temp-table tt1 field f1 as int. method public void m2(). find first tt1. end. end.
RB.openScope(tt1) appears in the pseudo-execute method for both Foo.java and Bar.java. The protection ensures only for this specific case.
#7 Updated by Constantin Asofiei 10 months ago
- Related to Bug #10567: same buffer can be used as argument multiple times added
#8 Updated by Constantin Asofiei 10 months ago
- Status changed from Review to Merge Pending
I'll merge after 10662a.
#9 Updated by Constantin Asofiei 10 months ago
- Status changed from Merge Pending to WIP
Branch 10483a was merged to trunk rev 16206 and archived.
What's left is to check if the solution needs to be refined.