question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Race condition in WorkScheduler

See original GitHub issue

I had just deployed a new beta of my app to a device and went to show my PM, I thought I had fixed all the known issues and I had tested well before. On the way to the PM the WiFi signal dropped and the phone went over to another network which needed credentials to be entered on a webpage for any traffic to let through.

My PM opened the App and 💥 crash! It had been opened just before I went to see my PM, so no more than a couple of minutes had passed, so the app didn’t re-load but was in the same state as I left it.

Anyways, something is not right and here is the crash log I have from HockeyApp:

Xamarin caused by: android.runtime.JavaProxyThrowable: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.InvalidOperationException: Cannot call Dequeue() on an empty queue
  at FFImageLoading.Concurrency.SimplePriorityQueue`2[TItem,TPriority].Dequeue () [0x0001f] in C:\projects\ffimageloading\source\FFImageLoading.Common\Concurrency\FastPriorityQueue\SimplePriorityQueue.cs:104 
  at FFImageLoading.Work.WorkScheduler+<TakeFromPendingTasksAndRunAsync>d__49.MoveNext () [0x0015b] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\WorkScheduler.cs:311 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at FFImageLoading.Work.WorkScheduler+<<TakeFromPendingTasksAndRun>b__47_0>d.MoveNext () [0x00024] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\WorkScheduler.cs:252 
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.InvalidOperationException: Cannot call Dequeue() on an empty queue
  at FFImageLoading.Concurrency.SimplePriorityQueue`2[TItem,TPriority].Dequeue () [0x0001f] in C:\projects\ffimageloading\source\FFImageLoading.Common\Concurrency\FastPriorityQueue\SimplePriorityQueue.cs:104 
  at FFImageLoading.Work.WorkScheduler+<TakeFromPendingTasksAndRunAsync>d__49.MoveNext () [0x0015b] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\WorkScheduler.cs:311 
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <3fd174ff54b146228c505f23cf75ce71>:0 
  at FFImageLoading.Work.WorkScheduler+<<TakeFromPendingTasksAndRun>b__47_0>d.MoveNext () [0x00024] in C:\projects\ffimageloading\source\FFImageLoading.Common\Work\WorkScheduler.cs:252 <---

Looking at the code where the exception originates from: https://github.com/luberda-molinet/FFImageLoading/blob/683ec66828b178d55ce51fe2887204aefcd7cfe9/source/FFImageLoading.Common/Work/WorkScheduler.cs#L304

while (tasksToRun.Count < numberOfTasks && PendingTasks.Count > 0)
{
    var task = PendingTasks.Dequeue();

The Dequeue call claims that PendingTasks.Count is 0 but you just checked right before that it wasn’t. This sounds like a race condition to me, something else must have done something to the PendingTasks to become 0.

Another problem is, that I cannot catch this exception, it bubbles up right until: https://github.com/luberda-molinet/FFImageLoading/blob/683ec66828b178d55ce51fe2887204aefcd7cfe9/source/FFImageLoading.Common/Work/WorkScheduler.cs#L241

Here you do:

protected void TakeFromPendingTasksAndRun()
{
    Task.Factory.StartNew(async () =>
    {
        await TakeFromPendingTasksAndRunAsync().ConfigureAwait(false); // FMT: we limit concurrent work using MaxParallelTasks
    }, CancellationToken.None, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler, TaskScheduler.Default).ConfigureAwait(false);
}

Since the Task is just wrapped in StartNew you are essentially doing async void. If something throws here, the entire App explodes. Please wrap this in a try/catch at least.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:13 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
rodhemphillcommented, Oct 19, 2017

Thanks guys. @Cheesebaron - I (now) understand mine is not the same issue - I’m happy to raise a different issue. @daniel-luberda Correct these are only logs and the app doesn’t crash - which means they must be trapped within the app somewhere (it’s not my app - I’ll -investigation this further). If I comment out the ffimageloading from the XAML the logs disappear plus they mention FFImageLoading continuously (there are thousands of lines of logs). The rest of the code does a “CanConnect” call before it attempts to access the network which fails at the time this error occurs. I have found your customer logger documentation so I’ll implement that and if there is still a problem I’ll log a different issue. Thanks for you help.

0reactions
Cheesebaroncommented, Oct 19, 2017

@rodhemphill you will see TaskAwaiter in your stack traces as soon as you use async/await… So tying those two together doesn’t automatically warrant a link to this issue. Yours is not related to this issue as the stack trace is entirely different. I clearly throws due to a Socket exception, which triggers another part of the code.

This issue is about a race condition which has been fixed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to prevent race condition in scheduler thats calls ...
The race conditions comes when the @Scheduled function runs and picks up downloadRequests that have been submitted for Async jobs but the ...
Read more >
What is a Race Condition?
A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the...
Read more >
Race condition
A race condition or race hazard is the condition of an electronics, software, or other system where the system's substantive behavior is dependent...
Read more >
Race conditions and deadlocks - Visual Basic
A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the...
Read more >
What Is a Race Condition? | Baeldung on Computer Science
By definition, a race condition is a condition of a program where its behavior depends on relative timing or interleaving of multiple threads...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found