Skip to content

Commit c8e3152

Browse files
nathan-miller23Nathan Miller
andauthored
handle backlog process startup failures (#3002)
Co-authored-by: Nathan Miller <nathanmiller@microsoft.com>
1 parent 84b015e commit c8e3152

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

src/StackExchange.Redis/PhysicalBridge.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -934,20 +934,40 @@ private void StartBacklogProcessor()
934934
{
935935
if (Interlocked.CompareExchange(ref _backlogProcessorIsRunning, 1, 0) == 0)
936936
{
937-
_backlogStatus = BacklogStatus.Activating;
938-
939-
// Start the backlog processor; this is a bit unorthodox, as you would *expect* this to just
940-
// be Task.Run; that would work fine when healthy, but when we're falling on our face, it is
941-
// easy to get into a thread-pool-starvation "spiral of death" if we rely on the thread-pool
942-
// to unblock the thread-pool when there could be sync-over-async callers. Note that in reality,
943-
// the initial "enough" of the back-log processor is typically sync, which means that the thread
944-
// we start is actually useful, despite thinking "but that will just go async and back to the pool"
945-
var thread = new Thread(s => ((PhysicalBridge)s!).ProcessBacklog())
937+
var successfullyStarted = false;
938+
try
939+
{
940+
_backlogStatus = BacklogStatus.Activating;
941+
942+
// Start the backlog processor; this is a bit unorthodox, as you would *expect* this to just
943+
// be Task.Run; that would work fine when healthy, but when we're falling on our face, it is
944+
// easy to get into a thread-pool-starvation "spiral of death" if we rely on the thread-pool
945+
// to unblock the thread-pool when there could be sync-over-async callers. Note that in reality,
946+
// the initial "enough" of the back-log processor is typically sync, which means that the thread
947+
// we start is actually useful, despite thinking "but that will just go async and back to the pool"
948+
var thread = new Thread(s => ((PhysicalBridge)s!).ProcessBacklog())
949+
{
950+
IsBackground = true, // don't keep process alive (also: act like the thread-pool used to)
951+
Name = "StackExchange.Redis Backlog", // help anyone looking at thread-dumps
952+
};
953+
954+
thread.Start(this);
955+
successfullyStarted = true;
956+
}
957+
catch (Exception ex)
946958
{
947-
IsBackground = true, // don't keep process alive (also: act like the thread-pool used to)
948-
Name = "StackExchange.Redis Backlog", // help anyone looking at thread-dumps
949-
};
950-
thread.Start(this);
959+
OnInternalError(ex);
960+
Trace("StartBacklogProcessor failed to start backlog processor thread: " + ex.Message);
961+
}
962+
finally
963+
{
964+
// If thread failed to start - reset flag to ensure next call doesn't erroneously think backlog process is running
965+
if (!successfullyStarted)
966+
{
967+
_backlogStatus = BacklogStatus.Inactive;
968+
Interlocked.Exchange(ref _backlogProcessorIsRunning, 0);
969+
}
970+
}
951971
}
952972
else
953973
{

0 commit comments

Comments
 (0)