-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
SaveChangesAsync doesn't preserve the sync context across retries #26763
Comments
@roji Disable the test for now? |
I think we've only seen it fail like once (AFAIK), will try to take a look at it in the next few days, if it fails again we can disable for sure... |
…22841 Dealing with this is tracked by dotnet#26763
@roji I am probably missing something, but it looks to me like SaveChangeAsync always uses var entitiesSaved = interceptionResult.HasResult
? interceptionResult.Result
: await DbContextDependencies.StateManager
.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken)
.ConfigureAwait(false); efcore/src/EFCore/DbContext.cs Line 730 in 197479e
|
@ajcvickers as discussed offline, ConfigureAwait controls where the continuation runs, i.e. the code after SaveChangesAsync - and we don't really care about that. |
@roji from the looks of it, SingleThreadSynchronizationContext22841 has the same issue SingleThreadSynchronizationContext had in npgsql (npgsql/npgsql/issues/3856). |
@vonzshik you're right - I just discovered that on my own; though that's just a test issue (note also that the test asserts on the current thread, rather than on the current sync context). Here's what I think is going on... Under normal circumstances, everything does work just fine; before AcceptAllChanges is called (the method that jumps into user code), all code is either synchronous, or asynchronous with ConfigureAwait(true). However, if we retry because of an actual error, then the 2nd attempt by the execution strategy will have lost the synchronization context, since the 1st attempt will have been called with |
Also failed in #27011 |
@roji what if the problem here is in If so, calling |
@vonzshik that's exactly what #27019 is supposed to address (I did it just 4 hours before your comment 😉). However, I can't see how SaveChangesAsync wouldn't yield... it's guaranteed to insert a row into SQL Server, which is supposed to always do networking and yield... If there's some situation in which SqlClient does sync I/O instead of async, then that would explain it; I'm not aware of such a thing (and it shouldn't happen), but it's possible. |
@roji It's not doing "networking" when using LocalDb. It's doing named-pipes. |
AFAIK that's still I/O that's supposed to be async... Put another way, if LocalDB communication were always sync, this test would have failed consistently, rather than being flaky. But maybe under some conditions SqlClient decides to do sync I/O... |
Well, for example, SqlClient's login handshake is sync only (because it's called from a constructor) |
😕 I'd still hope that ExecuteReaderAsync (as opposed to logging in) would actually be async - but you're right that we can't be sure... |
Keeping open for a few days to make sure we re-discuss in triage and see if the test failed after #27019. |
In this Helix build we have the following test failure, seems to be flaky:
The text was updated successfully, but these errors were encountered: