-
Notifications
You must be signed in to change notification settings - Fork 299
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
Merge | Merge netfx-specific exception handling #3179
base: main
Are you sure you want to change the base?
Conversation
Merge exception handling for SqlBulkCopy, SqlCommandBuilder, SqlDataReader, SqlInternalConnection, SqlTransaction and (partially) SqlConnection
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
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.
I'm a bit on the fence about this one, so I'd like to hear your thoughts before approving.
- My understanding of the constrained execution regions is that checking for
OutOfMemoryException
,StackOverflowException
,ThreadAbortException
is only required if there is a constrained execution region. I'm a bit concerned if this is a bit of a behavior change. - It looks to me that the plan is to have put the
bestEffortCleanup
in both netfx and netcore, but make it such that the netcoreBestEffortCleanup
implementation does nothing. I'm not a huge fan of this, since without digging into the implementations ofBestEffortCleanup
, it won't be obvious nothing is happening. I get that it'd be easier to merge the codebases, but I'm worried it won't be clear what's actually happening.
This isn't the first time something like this has come up, so I wonder if maybe we should come up with something that makes it clear the method call is only doing anything when in netfx or netcore. Sorta like how Debug.Assert
is expected to only run when it's a DEBUG build.
src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs
Show resolved
Hide resolved
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs
Outdated
Show resolved
Hide resolved
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3179 +/- ##
==========================================
- Coverage 72.81% 66.11% -6.71%
==========================================
Files 282 276 -6
Lines 59112 59074 -38
==========================================
- Hits 43045 39055 -3990
- Misses 16067 20019 +3952
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Thanks. The changes at the moment are no-ops, there's no behaviour change. An OutOfMemoryException without CERs means that the CLR's in an undefined state anyway, a StackOverflowException results in the process being killed and netcore doesn't throw ThreadAbortExceptions at all. What about wrapping every call to BestEffortCleanup in |
I think the only instances where was most concerned about behavior change was when the new catches were added when there wasn't a catch-all exception handler. All the other instances are fine since they basically do the same thing as the catch-all handler. My understanding, too, is that we really only have the CERs in place to handle situations where SqlClient is being called from SQL Server CLR. The theory being that the CER is there to protect SQL Server from crashing if something goes wrong with SqlClient. Outside of those situations, I don't care as much about cleanup behavior. I suppose my primary issue is whether we'll try to clean things up in netcore that were not being cleaned up before.
Yeah.... that's what I had been doing for the merge I've been working on for SqlTransaction. It's messy as all heck, but it's generally clear that the code is being used or not. I've even been wrapping the extra catch blocks in the same One experiment I was trying (and this prompted removing the resilience sections) was to use an inline function to implement the meat and potatoes of the method and either call it directly (in netcore) or pass it into a method that wraps it with appropriate CES handling. It appears that by using inline functions, it's only marginally less performant, but cleans up the code a lot. Something like: public void MyMethod()
{
void DoTheStuff()
{
// stuff
}
#if NETFRAMEWORK
callWithCes(DoTheStuff)
#else
DoTheStuff();
#endif
} of course what would be really nice is if we could just get rid of CERs... |
I understand. These three exceptions fall into two groups though:
I'll do that, thanks. I think BestEffortCleanup is the best place to draw the line, since its body relies on details of TdsParserStateObject which can't be merged and the catch blocks are functionally no-ops. |
Wrapped each call to SqlInternalConnection.BestEffortCleanup in #if, rather than having an empty BestEffortCleanup method.
These were part of the netfx exception handling
Contributes to #2965 and #1261.
This PR merges the exception handling for ThreadAbortException, StackOverflowException and OutOfMemoryException between .NET Core and .NET Framework.
Following this PR, it becomes fairly trivial to merge SqlBulkCopy, SqlDataReader and SqlTransaction.
Given the number of indentation changes from try/catch blocks, I'd recommend switching off whitespace when checking the diff - it eliminates around a third of it.
I'd appreciate a CI run for this.