Bug 10911 - Stackoverflow while using PLinq
Summary: Stackoverflow while using PLinq
Status: RESOLVED FIXED
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Core ()
Version: 2.10.x
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-03-05 10:16 UTC by vlad.dimitrov
Modified: 2016-04-16 09:13 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 vlad.dimitrov 2013-03-05 10:16:46 UTC
Recently I received a strange error on one of our servers which run mono 2.10.8.1 on Ubuntu 12.4:

System.AggregateException: One or more errors occured ---> System.StackOverflowException: The requested operation caused a stack overflow.
  at System.Collections.Concurrent.SplitOrderedList`2[System.String,System.Collections.Generic.KeyValuePair`2[System.String,System.Collections.Generic.IEnumerable`1[Warehouse.Sync.Common.ChangeItem]]].GetParent (UInt32 v) [0x00000] in <filename unknown>:0
  at System.Collections.Concurrent.SplitOrderedList`2[System.String,System.Collections.Generic.KeyValuePair`2[System.String,System.Collections.Generic.IEnumerable`1[Warehouse.Sync.Common.ChangeItem]]].InitializeBucket (UInt32 b) [0x00000] in <filename unknown>:0
  at System.Collections.Concurrent.SplitOrderedList`2[System.String,System.Collections.Generic.KeyValuePair`2[System.String,System.Collections.Generic.IEnumerable`1[Warehouse.Sync.Common.ChangeItem]]].InitializeBucket (UInt32 b) [0x00000] in <filename unknown>:0
  at System.Collections.Concurrent.SplitOrderedList`2[System.String,System.Collections.Generic.KeyValuePair`2[System.String,System.Collections.Generic.IEnumerable`1[Warehouse.Sync.Common.ChangeItem]]].InitializeBucket (UInt32 b) [0x00000] in <filename unknown>:0

This continued in the logs for several megabytes. Looking at the code (https://github.com/mosa/Mono-Class-Libraries/blob/master/mcs/class/corlib/System.Collections.Concurrent/SplitOrderedList.cs) it looks normal to happen.

Looks like if InitializeBucket receives 0 then GetParrent will return 0. GetBucket can return null too if list it checks in is empty and then the whole thing gets into infinite recursion.

I cannot provide an example which causes this error as it happened on a server and while trying to reproduce on Windows/.NET the operation did not crash and the context changed. After that I have not noticed similar errors.

The server has a 4 core CPU if that would be of any help.
Comment 1 Jérémie Laval 2013-03-05 10:32:54 UTC
There is a head sentinel node in position 0 to avoid this recursion which is supposed to stay forever so it's unlikely to be the cause.

Could you extract your PLinq query and post it here?
Comment 2 vlad.dimitrov 2013-03-05 11:41:08 UTC
This is a shortened version of the class:

    public class ChangeSet : List<ChangeItem>
    {
        public ChangeSet ()
        {
        }

        public void Optimize ()
        {
            ChangeItem [] toRemove = this.AsParallel ()
                .ToLookup (c => c.Table + ":" + c.IdValue, c => c)
                .SelectMany (group =>
                    {
                        List<ChangeItem> current = @group.ToList ();
                        if (current.Count == 1)
                            return new List<ChangeItem> ();

                        return current;
                    }).ToArray ();

            foreach (ChangeItem item in toRemove)
                Remove (item);
        }
    }
Comment 3 Marek Safar 2016-04-16 09:13:09 UTC
Should be fixed, we switched to reference source implementation