-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Ensure HttpListener request buffer is aligned as required by the host processor #25563
Changes from all commits
4f18b04
03a3424
d0fd8b8
7305eba
6e0465e
fd0667f
3ae9b26
6c21edb
3f90e6f
8ad7f1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,14 +3,16 @@ | |
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace System.Net | ||
{ | ||
internal abstract unsafe class RequestContextBase : IDisposable | ||
{ | ||
private Interop.HttpApi.HTTP_REQUEST* _memoryBlob; | ||
private Interop.HttpApi.HTTP_REQUEST* _originalBlobAddress; | ||
private byte[] _backingBuffer; | ||
private IntPtr _backingBuffer = IntPtr.Zero; | ||
private int _backingBufferLength = 0; | ||
|
||
// Must call this from derived class' constructors. | ||
protected void BaseConstruction(Interop.HttpApi.HTTP_REQUEST* requestBlob) | ||
|
@@ -29,7 +31,7 @@ protected void BaseConstruction(Interop.HttpApi.HTTP_REQUEST* requestBlob) | |
// before an object (HttpListenerRequest) which closes the RequestContext on demand is returned to the application. | ||
internal void ReleasePins() | ||
{ | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == null, "RequestContextBase::ReleasePins()|ReleasePins() called twice."); | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == IntPtr.Zero, "RequestContextBase::ReleasePins()|ReleasePins() called twice."); | ||
_originalBlobAddress = _memoryBlob; | ||
UnsetBlob(); | ||
OnReleasePins(); | ||
|
@@ -48,7 +50,14 @@ public void Dispose() | |
Dispose(true); | ||
} | ||
|
||
protected virtual void Dispose(bool disposing) { } | ||
protected virtual void Dispose(bool disposing) | ||
{ | ||
if (_backingBuffer != IntPtr.Zero) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please review IDisposable pattern. Not sure if you should add an 'if' check for "disposing == true" here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that the current behavior is correct, based on this page. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok. What about a 'finalizer'? Does this have one already and do we need one? Reading the pattern description from your link above says this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RequestContextBase does implement a finalizer that calls Dispose(bool), freeing the unmanaged resources it has acquired. I'm not very familiar with the pattern though, so I'll read through the rest of that dispose/finalize article and make sure I'm doing everything correctly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've checked it out and am confident the dispose pattern is correctly implemented here. |
||
{ | ||
Marshal.FreeHGlobal(_backingBuffer); | ||
_backingBuffer = IntPtr.Zero; | ||
} | ||
} | ||
|
||
~RequestContextBase() | ||
{ | ||
|
@@ -59,12 +68,12 @@ internal Interop.HttpApi.HTTP_REQUEST* RequestBlob | |
{ | ||
get | ||
{ | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == null, "RequestContextBase::Dispose()|RequestBlob requested after ReleasePins()."); | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == IntPtr.Zero, "RequestContextBase::Dispose()|RequestBlob requested after ReleasePins()."); | ||
return _memoryBlob; | ||
} | ||
} | ||
|
||
internal byte[] RequestBuffer | ||
internal IntPtr RequestBuffer | ||
{ | ||
get | ||
{ | ||
|
@@ -76,7 +85,7 @@ internal uint Size | |
{ | ||
get | ||
{ | ||
return (uint)_backingBuffer.Length; | ||
return (uint)_backingBufferLength; | ||
} | ||
} | ||
|
||
|
@@ -91,7 +100,7 @@ internal IntPtr OriginalBlobAddress | |
|
||
protected void SetBlob(Interop.HttpApi.HTTP_REQUEST* requestBlob) | ||
{ | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == null, "RequestContextBase::Dispose()|SetBlob() called after ReleasePins()."); | ||
Debug.Assert(_memoryBlob != null || _backingBuffer == IntPtr.Zero, "RequestContextBase::Dispose()|SetBlob() called after ReleasePins()."); | ||
if (requestBlob == null) | ||
{ | ||
UnsetBlob(); | ||
|
@@ -116,7 +125,16 @@ protected void UnsetBlob() | |
|
||
protected void SetBuffer(int size) | ||
{ | ||
_backingBuffer = size == 0 ? null : new byte[size]; | ||
if (_backingBuffer != IntPtr.Zero) | ||
{ | ||
Marshal.FreeHGlobal(_backingBuffer); | ||
} | ||
|
||
_backingBuffer = size == 0 ? IntPtr.Zero : Marshal.AllocHGlobal(size); | ||
_backingBufferLength = size; | ||
|
||
// Zero out the contents of the buffer. | ||
new Span<byte>(_backingBuffer.ToPointer(), size).Fill(0); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vast majority of the line changes in this file are the result of removing these fixed statements, and thus changing the indentation for large blocks of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, if you append ?w=1 to the GitHub url, it'll ignore whitespace differences:
https://github.com/dotnet/corefx/pull/25563/files?w=1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know!