-
Notifications
You must be signed in to change notification settings - Fork 311
Add partial packet detection and fixup #2714
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
Changes from all commits
94b6808
53c1139
3622f9c
d0fd956
25f0c62
cc694b9
fb9be3b
7f262eb
67b7762
57c8b86
b00a379
352ac25
51137f9
17ad988
eae759a
29ad90b
5d3f8a6
36cdd88
433ccf7
c65da55
b4460ec
80cbb6e
bb4fa9e
79f9fbc
d31e908
429b7ac
11dd84e
7684861
cd1e025
3ed9c83
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 |
---|---|---|
|
@@ -322,14 +322,22 @@ private void ReadSniError(TdsParserStateObject stateObj, uint error) | |
stateObj.SendAttention(mustTakeWriteLock: true); | ||
|
||
PacketHandle syncReadPacket = default; | ||
bool readFromNetwork = true; | ||
RuntimeHelpers.PrepareConstrainedRegions(); | ||
bool shouldDecrement = false; | ||
try | ||
{ | ||
Interlocked.Increment(ref _readingCount); | ||
shouldDecrement = true; | ||
|
||
syncReadPacket = ReadSyncOverAsync(stateObj.GetTimeoutRemaining(), out error); | ||
readFromNetwork = !PartialPacketContainsCompletePacket(); | ||
samsharma2700 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (readFromNetwork) | ||
{ | ||
syncReadPacket = ReadSyncOverAsync(stateObj.GetTimeoutRemaining(), out error); | ||
} | ||
else | ||
{ | ||
error = TdsEnums.SNI_SUCCESS; | ||
samsharma2700 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
Interlocked.Decrement(ref _readingCount); | ||
shouldDecrement = false; | ||
|
@@ -342,7 +350,7 @@ private void ReadSniError(TdsParserStateObject stateObj, uint error) | |
} | ||
else | ||
{ | ||
Debug.Assert(!IsValidPacket(syncReadPacket), "unexpected syncReadPacket without corresponding SNIPacketRelease"); | ||
Debug.Assert(!readFromNetwork || !IsValidPacket(syncReadPacket), "unexpected syncReadPacket without corresponding SNIPacketRelease"); | ||
fail = true; // Subsequent read failed, time to give up. | ||
} | ||
} | ||
|
@@ -353,7 +361,7 @@ private void ReadSniError(TdsParserStateObject stateObj, uint error) | |
Interlocked.Decrement(ref _readingCount); | ||
} | ||
|
||
if (!IsPacketEmpty(syncReadPacket)) | ||
if (readFromNetwork && !IsPacketEmpty(syncReadPacket)) | ||
{ | ||
ReleasePacket(syncReadPacket); | ||
} | ||
|
@@ -393,60 +401,9 @@ private void ReadSniError(TdsParserStateObject stateObj, uint error) | |
AssertValidState(); | ||
} | ||
|
||
public void ProcessSniPacket(PacketHandle packet, uint error) | ||
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. Can we still keep the older function? I am still trying to understand all the checks that were removed with the new function call. 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. The previous version of |
||
private uint GetSniPacket(PacketHandle packet, ref uint dataSize) | ||
{ | ||
if (error != 0) | ||
{ | ||
if ((_parser.State == TdsParserState.Closed) || (_parser.State == TdsParserState.Broken)) | ||
{ | ||
// Do nothing with callback if closed or broken and error not 0 - callback can occur | ||
// after connection has been closed. PROBLEM IN NETLIB - DESIGN FLAW. | ||
return; | ||
} | ||
|
||
AddError(_parser.ProcessSNIError(this)); | ||
AssertValidState(); | ||
} | ||
else | ||
{ | ||
uint dataSize = 0; | ||
|
||
uint getDataError = SNIPacketGetData(packet, _inBuff, ref dataSize); | ||
|
||
if (getDataError == TdsEnums.SNI_SUCCESS) | ||
{ | ||
if (_inBuff.Length < dataSize) | ||
{ | ||
Debug.Assert(true, "Unexpected dataSize on Read"); | ||
throw SQL.InvalidInternalPacketSize(StringsHelper.GetString(Strings.SqlMisc_InvalidArraySizeMessage)); | ||
} | ||
|
||
_lastSuccessfulIOTimer._value = DateTime.UtcNow.Ticks; | ||
_inBytesRead = (int)dataSize; | ||
_inBytesUsed = 0; | ||
|
||
if (_snapshot != null) | ||
{ | ||
_snapshot.AppendPacketData(_inBuff, _inBytesRead); | ||
if (_snapshotReplay) | ||
{ | ||
_snapshot.MoveNext(); | ||
#if DEBUG | ||
_snapshot.AssertCurrent(); | ||
#endif | ||
} | ||
} | ||
|
||
SniReadStatisticsAndTracing(); | ||
SqlClientEventSource.Log.TryAdvancedTraceBinEvent("TdsParser.ReadNetworkPacketAsyncCallback | INFO | ADV | State Object Id {0}, Packet read. In Buffer: {1}, In Bytes Read: {2}", ObjectID, _inBuff, _inBytesRead); | ||
|
||
AssertValidState(); | ||
} | ||
else | ||
{ | ||
throw SQL.ParsingError(ParsingErrorState.ProcessSniPacketFailed); | ||
} | ||
} | ||
return SNIPacketGetData(packet, _inBuff, ref dataSize); | ||
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. Do you think it will be possible to avoid this function hop 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. Possibly. It's part of the separation between the managed and unmanaged SNI implementations and looks like it's currently just a function to function indirection to the override. If it's really important I can collapse it but it's unlikely to cause any problems and it keeps the existing structure in place for those familiar with the layering making it easier to understand. |
||
} | ||
|
||
private void ChangeNetworkPacketTimeout(int dueTime, int period) | ||
|
@@ -535,7 +492,7 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) | |
bool processFinallyBlock = true; | ||
try | ||
{ | ||
Debug.Assert(CheckPacket(packet, source) && source != null, "AsyncResult null on callback"); | ||
Debug.Assert((packet.Type == 0 && PartialPacketContainsCompletePacket()) || (CheckPacket(packet, source) && source != null), "AsyncResult null on callback"); | ||
|
||
if (_parser.MARSOn) | ||
{ | ||
|
@@ -547,7 +504,7 @@ public void ReadAsyncCallback(IntPtr key, PacketHandle packet, uint error) | |
|
||
// The timer thread may be unreliable under high contention scenarios. It cannot be | ||
// assumed that the timeout has happened on the timer thread callback. Check the timeout | ||
// synchrnously and then call OnTimeoutSync to force an atomic change of state. | ||
// synchronously and then call OnTimeoutSync to force an atomic change of state. | ||
if (TimeoutHasExpired) | ||
{ | ||
OnTimeoutSync(asyncClose: true); | ||
|
@@ -1633,7 +1590,7 @@ internal void AssertStateIsClean() | |
if ((parser != null) && (parser.State != TdsParserState.Closed) && (parser.State != TdsParserState.Broken)) | ||
{ | ||
// Async reads | ||
Debug.Assert(_snapshot == null && !_snapshotReplay, "StateObj has leftover snapshot state"); | ||
Debug.Assert(_snapshot == null && _snapshotStatus == SnapshotStatus.NotActive, "StateObj has leftover snapshot state"); | ||
Debug.Assert(!_asyncReadWithoutSnapshot, "StateObj has AsyncReadWithoutSnapshot still enabled"); | ||
Debug.Assert(_executionContext == null, "StateObj has a stored execution context from an async read"); | ||
// Async writes | ||
|
Uh oh!
There was an error while loading. Please reload this page.