Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop ignoring real buffers shrunk to 0 size #3157

Open
wants to merge 1 commit into
base: devel
Choose a base branch
from

Conversation

celskeggs
Copy link
Contributor

Related Issue(s) n/a
Has Unit Tests (y/n) n
Documentation Included (y/n) n

Change Description

If BufferManager is asked to allocate a buffer when it has no more buffers, it will return a null, zero-size buffer. Therefore, if BufferManager receives a request to deallocate a zero-sized buffer, it discards the buffer, on the assumption that it resulted from a failed allocation.

However, if a user allocates a buffer from BufferManager, they are allowed to decrease the size before they deallocate it. Therefore, a zero size buffer passed to the deallocation function cannot necessarily be discarded; it could be a real buffer that needs to be freed. Only discard deallocated buffers if they are empty and null.

Rationale

Without this fix, trying to return allocated buffers to a BufferManager with sizes updated to 0 can result in a memory leak.

Testing/Review Recommendations

No specific recommendations.

Future Work

No future work.

Without this fix, trying to return allocated buffers to a BufferManager
with sizes updated to 0 can result in a memory leak.
@LeStarch
Copy link
Collaborator

My first thought was to recommend using not buffer.isValid(); to check for invalid buffers to skip. However, to be valid according to the function, a buffer must be not null, and not zero-sized.

bool Buffer::isValid() const {
return (this->m_bufferData != nullptr) && (this->m_size > 0);
}

I agree with you fix, because it is absolutely legal to shrink a buffer (even to zero) and still have it be deallocated. My question is, should the isValid buffer method be updated to reflect this?

@bocchino you added this Fw::Buffer::isValid method originally (if my memory holds). Was there a reason to consider a buffer valid only if it has positive size? Why not just check to see if the memory pointer is null

@LeStarch
Copy link
Collaborator

This would be a good issue to put into a Unit-Test to prevent regressions.

Copy link
Collaborator

@LeStarch LeStarch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks solid.

@bocchino
Copy link
Collaborator

Was there a reason to consider a buffer valid only if it has positive size?

I think a buffer with a zero size and a non-null pointer is invalid. It can't be used to store any data, any more than a buffer with a positive size and a null pointer.

It seems like we are now using the pointer value to track side-band information of the form "this buffer was valid when the buffer manager gave it out, but it was made invalid by shrinking its size to zero" as opposed to "this buffer was invalid when the buffer manager gave it out." The size-shrinking and consequent valid-to-invalid transformation were not part of the original design.

I've never been entirely comfortable with the size-shrinking pattern, but I think it is now ingrained in F Prime, because there's no field in the buffer class for storing how much of the original allocation is used. In hindsight it might have been better to have two fields: one for the original allocation, and one for how much is used. But given how buffers currently work, the solution proposed in this PR seems good.

// null, empty buffers if it can't allocate one.
// however, empty non-null buffers could potentially be previously allocated
// buffers with their size reduced. the user is allowed to make buffers smaller.
if (fwBuffer.getData() == nullptr && fwBuffer.getSize() == 0) {
this->log_WARNING_HI_ZeroSizeBuffer();
Copy link
Collaborator

@bocchino bocchino Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we rename this event to NullEmptyBuffer instead of ZeroSizeBuffer? Or maybe just NullBuffer?

@bocchino
Copy link
Collaborator

It looks like the current BufferManager implementation allows a zero-size buffer allocation. Allocating and returning such a buffer would also cause a memory leak in the old code (though it's an unlikely use case). Checking for a null pointer instead of a zero size fixes this issue as well.

@bocchino
Copy link
Collaborator

It's not clear to me that the BufferManager should allow allocations of zero-size buffers, which are invalid, but it does.

@celskeggs
Copy link
Contributor Author

Allowing zero-sized allocations is a strange edge case, but it can make some tests simpler for us to allow it. (I caught this bug in a test where I randomly generated buffers of length 0 to N, and occasionally it landed on 0.) I don't see any reason to forbid them outright in a core framework component. I agree that this PR also fixes that issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants