Skip to content

Commit 33de935

Browse files
Filter fatal exceptions from Task.FromException in async paths
Fatal exceptions (OOM, StackOverflow, ThreadAbort, NullReference, AccessViolation) must not be wrapped in Task.FromException or TrySetException — they should propagate synchronously. Add ADP.IsCatchableExceptionType guards matching the existing pattern used elsewhere in SqlDataReader. Sites fixed: - SqlBulkCopy.cs: 8 catch blocks guarded with exception filter - SqlDataReader.cs (InvokeAsyncCall): exception filter added - SqlCommand.Reader.cs: exception filter added - SqlCommand.Xml.cs: exception filter added Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 52ed94b commit 33de935

4 files changed

Lines changed: 15 additions & 11 deletions

File tree

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBulkCopy.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,10 @@ private Task ReadFromRowSourceAsync(CancellationToken cts)
13601360
{
13611361
if (_isAsyncBulkCopy)
13621362
{
1363+
if (!ADP.IsCatchableExceptionType(ex))
1364+
{
1365+
throw;
1366+
}
13631367
return Task.FromException<bool>(ex);
13641368
}
13651369
else
@@ -2530,7 +2534,7 @@ private Task CopyColumnsAsync(int col, TaskCompletionSource<object> source = nul
25302534
source.SetResult(null);
25312535
}
25322536
}
2533-
catch (Exception ex)
2537+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
25342538
{
25352539
if (source != null)
25362540
{
@@ -2739,7 +2743,7 @@ private Task CopyRowsAsync(int rowsSoFar, int totalRows, CancellationToken cts,
27392743
source.TrySetResult(null); // This is set only on the last call of async copy. But may not be set if everything runs synchronously.
27402744
}
27412745
}
2742-
catch (Exception ex)
2746+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
27432747
{
27442748
if (source != null)
27452749
{
@@ -2816,7 +2820,7 @@ private Task CopyBatchesAsync(BulkCopySimpleResultSet internalResults, string up
28162820
}
28172821
}
28182822
}
2819-
catch (Exception ex)
2823+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
28202824
{
28212825
if (source != null)
28222826
{
@@ -2888,7 +2892,7 @@ private Task CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults,
28882892
return CopyBatchesAsyncContinuedOnSuccess(internalResults, updateBulkCommandText, cts, source);
28892893
}
28902894
}
2891-
catch (Exception ex)
2895+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
28922896
{
28932897
if (source != null)
28942898
{
@@ -2950,7 +2954,7 @@ private Task CopyBatchesAsyncContinuedOnSuccess(BulkCopySimpleResultSet internal
29502954
return source.Task;
29512955
}
29522956
}
2953-
catch (Exception ex)
2957+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
29542958
{
29552959
if (source != null)
29562960
{
@@ -3122,7 +3126,7 @@ private void WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet int
31223126
}
31233127
}
31243128
}
3125-
catch (Exception ex)
3129+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
31263130
{
31273131
_localColumnMappings = null;
31283132

@@ -3299,7 +3303,7 @@ private void WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletio
32993303
WriteToServerInternalRestContinuedAsync(internalResults, cts, source); // internalResults is valid here.
33003304
}
33013305
}
3302-
catch (Exception ex)
3306+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
33033307
{
33043308
if (source != null)
33053309
{
@@ -3376,7 +3380,7 @@ private Task WriteToServerInternalAsync(CancellationToken ctoken)
33763380
return resultTask;
33773381
}
33783382
}
3379-
catch (Exception ex)
3383+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
33803384
{
33813385
if (source != null)
33823386
{

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.Reader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ private void BeginExecuteReaderInternalReadStage(TaskCompletionSource<object> co
381381
_stateObj.ReadSni(completion);
382382
}
383383
// @TODO: CER Exception Handling was removed here (see GH#3581)
384-
catch (Exception e)
384+
catch (Exception e) when (ADP.IsCatchableExceptionType(e))
385385
{
386386
// Similarly, if an exception occurs put the stateObj back into the pool.
387387
// and reset async cache information to allow a second async execute

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommand.Xml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ private void BeginExecuteXmlReaderInternalReadStage(TaskCompletionSource<object>
334334
_stateObj.ReadSni(completion);
335335
}
336336
// @TODO: CER Exception Handling was removed here (see GH#3581)
337-
catch (Exception e)
337+
catch (Exception e) when (ADP.IsCatchableExceptionType(e))
338338
{
339339
// Similarly, if an exception occurs put the stateObj back into the pool.
340340
// and reset async cache information to allow a second async execute

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDataReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5476,7 +5476,7 @@ private Task<T> InvokeAsyncCall<T>(SqlDataReaderBaseAsyncCallContext<T> context)
54765476
{
54775477
task = context.Execute(null, context);
54785478
}
5479-
catch (Exception ex)
5479+
catch (Exception ex) when (ADP.IsCatchableExceptionType(ex))
54805480
{
54815481
task = Task.FromException<T>(ex);
54825482
}

0 commit comments

Comments
 (0)