Bug 19420 - Setting sgen nursery-size=2g causes memory allocation error
Summary: Setting sgen nursery-size=2g causes memory allocation error
Alias: None
Product: Runtime
Classification: Mono
Component: GC ()
Version: 3.2.x
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2014-04-30 11:28 UTC by Craig Minihan
Modified: 2014-07-30 11:17 UTC (History)
3 users (show)

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:

Description Craig Minihan 2014-04-30 11:28:14 UTC
Mono 3.4.0 (tarball) on CentOS 6.4, at prompt enter the following:

$ export MONO_GC_PARAMS=nursery-size=2g
$ csharp
Error: Garbage collector could not allocate 18446744071562067968 bytes of memory for nursery.

The number reported equates to 17179869182 GB.

I've used csharp here since you don't need any app code to see the issue - the mono executable has exactly the same issue.

The number reported in the message is always the same.

I've just tried setting to 4g it looks like it enters an infinite loop with no error reported.

Eyeballing the code shows this as looking hooky:
(from mono_gc_base_init() in sgen-gc.c)
	sgen_nursery_size = val;
	sgen_nursery_bits = 0;
	while (1 << (++ sgen_nursery_bits) != sgen_nursery_size);

I'm not sure on the significance of sgen_nursery_bits but I don't think it should be used to shift on each iteration.
Comment 1 Craig Minihan 2014-04-30 12:43:13 UTC
sgen_nursery_size is an int, so any values > 2g will cause it to overflow on the shift and never make the match. Unfortunately this means to fix that problem the global var sgen_nursery_size must be changed from an int to a long. I suspect this will cause badness elsewhere. Also, the 1 should become 1L in the shift logic.
Comment 2 Craig Minihan 2014-04-30 12:59:49 UTC
Changing sgen_nursery_size to long and changing alloc_nursery()'s alloc_size to long fixes the 2g case. For 4g and greater there seems to be another infinite loop which I've not tracked thru yet. If I get time I'll trace it further and submit a PR.

I know this is an odd case (nursery >= 2gb) but in the context of v large servers 2gb can be < 1% of RAM. It is useful to test higher values to see the effect on performance - alternately sgen shouldn't barf when asked for large values.
Comment 3 Rodrigo Kumpera 2014-05-21 01:05:52 UTC
Hi Craig, I pushed a bunch of fixes to field sizes. Does it work for you now?
Comment 4 Craig Minihan 2014-07-30 11:17:48 UTC
Looks good in 3.6.1 now.