Skip to content

Conversation

chrisejones
Copy link

This commit fixes an issue where the buffer used by the DriverProxy class can become unpinned causing clients to send corrupt messages to the Media Driver.

UnsafeBuffer has a constructor that takes a ByteBuffer. ByteBuffer contains a pointer to a managed array that has been pinned with a GCHandle. When an UnsafeBuffer is constructed from a ByteBuffer it takes a copy of the pointer, but does not take ownership of the GCHandle. If the ByteBuffer is allowed to be garbage collected the GCHandle is freed in its finalizer unpinning the managed array. The unpinned array may be moved by the garbage collector leaving UnsafeBuffer pointing to invalid memory.

This commit fixes the bug by ensuring that we keep a reference to the ByteBuffer that is wrapped by the UnsafeBuffer in DriverProxy. This prevents the garbage collector from calling the ByteBuffer's finalizer and unpinning the managed array whilst it is still being used by the DriverProxy. It also fixes a similar issue in the SimplePublisher sample.

An more invasive, but cleaner, fix would be to give UnsafeBuffer a constructor that did the job of the ByteBuffer - creating a pointer to an array with the correct alignment. I think that in all cases that a ByteBuffer is used it's immediately passed into an UnsafeBuffer. Please let me know if you would prefer that instead.

This commit fixes an issue where the buffer used by the DriverProxy class can become unpinned causing clients to send corrupt messages to the Media Driver.

UnsafeBuffer has a constructor that takes a ByteBuffer.  ByteBuffer contains a pointer to a managed array that has been pinned with a GCHandle.  When an UnsafeBuffer is constructed from a ByteBuffer it takes a copy of the pointer, but does not take ownership of the GCHandle.  If the ByteBuffer is allowed to be garbage collected the GCHandle is freed in its finalizer unpinning the managed array.  The unpinned array may be moved by the garbage collector leaving UnsafeBuffer pointing to invalid memory.

This commit fixes the bug by ensuring that we keep a reference to the ByteBuffer that is wrapped by the UnsafeBuffer in DriverProxy. This prevents the garbage collector from calling the ByteBuffer's finalizer and unpinning the managed array whilst it is still being used by the DriverProxy.  It also fixes a similar issue in the SimplePublisher sample.
@JPWatson
Copy link
Collaborator

Good catch! My preference would be to keep the ByteBuffer in a field of the UnsafeBuffer.

https://github.com/real-logic/agrona/blob/master/agrona/src/main/java/org/agrona/concurrent/UnsafeBuffer.java#L182

Let me know if you want to give it a go or I can sort it.

@JPWatson
Copy link
Collaborator

@JPWatson
Copy link
Collaborator

Fixed. Thank you for you help.

@JPWatson JPWatson closed this Aug 17, 2017
@chrisejones chrisejones deleted the driver-proxy-buffer-fix branch March 15, 2018 21:46
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.

2 participants