Bug 18421 - ConcurrentQueue<T>.TryDequeue leaks last remaining element.
Summary: ConcurrentQueue<T>.TryDequeue leaks last remaining element.
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: mscorlib ()
Version: 3.2.x
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: marcos.henrich
URL:
Depends on:
Blocks:
 
Reported: 2014-03-17 09:12 UTC by kissling
Modified: 2014-05-30 15:15 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description kissling 2014-03-17 09:12:13 UTC
When dequeueing elements from a ConcurrentQueue<T>, the last element is still getting referenced by the queue until a new element is added.

Steps to reproduce:
1. Create a class that logs its creation and destruction (finalizer)
2. Add multiple instances of this class to the ConcurrentQueue.
3. Dequeue all of the instances from the queue and discard them by not assigning them to a variable.
4. Force GC collection (GC.Collect(), GC.WaitForPendingFinalizers())

Expected results:
5. All instances are collected.

Actual results:
5. Notice that the last instance has not been collected!

now, either:
6. Set the queue reference to null
7. Force GC collection again
8. With the queue being collected, the last instance of the custom class is now also collected.

or:
6. Add a new element to the queue
7. Force GC collection again
8. The old element is now properly collected (while the new one is now leaked :) )


Discussion:
This is a major problem, as code that depends on finalizers doesn't expect a queue to hold references to dequeued objects.
One example is a queue where System.Threading.Tasks get submitted. Those tasks propagate unobserved exceptions to the TaskScheduler's UnobservedTaskExceptionHandler, when they are garbage collected. However, due to this ConcurrentQueue issue, those exceptions don't get reported - or they get reported with a delay - depending on how extensively the queue is used.

The problem's source seems to stem from the early return statement in the "if (next == null)" branch of the TryDequeue implementation as seen by the assembly browser. In this case, this.head and this.tail are not properly updated.

Workaround:
Use a standard Queue with a lock :-) At least one can understand the code behind the standard queue, and the performance is enough for most cases anyway.


Version information:

=== Xamarin Studio ===

Version 4.2.3 (build 60)
Installation UUID: 938751df-f7a5-457d-b87b-379763e0ada1
Runtime:
	Mono 3.2.6 ((no/9b58377)
	GTK+ 2.24.23 theme: Raleigh
	GTK# (2.12.0.0)
	Package version: 302060000

=== Apple Developer Tools ===

Xcode 5.1 (5084)
Build 5B130a

=== Xamarin.iOS ===

Version: 7.2.0.2 (Business Edition)
Hash: 58c3efa
Branch: 
Build date: 2014-10-03 18:02:26-0400

=== Xamarin.Android ===

Version: 4.12.1 (Business Edition)
Android SDK: /Users/etankissling/Library/Developer/Xamarin/android-sdk-mac_x86
	Supported Android versions:
		4.3 (API level 18)
Java SDK: /usr
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

=== Xamarin.Mac ===

Xamarin.Mac: Not Installed

=== Build Information ===

Release ID: 402030060
Git revision: 30c4afc300c2a39ec5300851357ce02e49dd217e
Build date: 2014-03-05 22:09:33+0000
Xamarin addins: f8a9589b57c2bfab2ccd73c880e7ad81e3ecf044

=== Operating System ===

Mac OS X 10.9.2
Darwin Etans-MacBook-Pro.local 13.1.0 Darwin Kernel Version 13.1.0
    Thu Jan 16 19:40:37 PST 2014
    root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64
Comment 1 marcos.henrich 2014-05-29 13:23:51 UTC
Hi kissling,

Thank you for the detailed bug report.
A pull request for this issue can be found here  https://github.com/mono/mono/pull/1068.
Comment 2 marcos.henrich 2014-05-30 15:15:34 UTC
Fixed in master 7c52a7bf5fe10f70b547b37f757a9ad022d29d1f.