Bug #24751 Possible infinite loop in init_io_cache() when insufficient memory
Submitted: 1 Dec 2006 12:00 Modified: 1 Feb 2007 1:38
Reporter: Tomash Brechko Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: General Severity:S3 (Non-critical)
Version:4.1, 5.0, 5.1 OS:Linux (Linux)
Assigned to: Kristofer Pettersson CPU Architecture:Any

[1 Dec 2006 12:00] Tomash Brechko
Description:
There's a possibility for an infinite loop in init_io_cache() on insufficient memory condition.

How to repeat:
Under bash do 'ulimit -S -v 110000' before running mysqld, then start the server and run the attached script.

Suggested fix:
In mysys/mf_iocache.c there is the code:

    for (;;)
    {
      uint buffer_block;
(1)   cachesize=(uint) ((ulong) (cachesize + min_cache-1) &
			(ulong) ~(min_cache-1));
      if (cachesize < min_cache)
	cachesize = min_cache;

    ...

      if (cachesize == min_cache)
	DBUG_RETURN(2);				/* Can't alloc cache */
(2)   cachesize= (uint) ((long) cachesize*3/4); /* Try with less memory */
    }

Now imagine if min_cache == 100b, and cachesize == 1100b.  At (1) we mask do ((1100b+100b-1)==1111b) & (~(100b-1)==1100b)==1100b, so cachesize is unchanged.  At (2) 1100b*3/4 == 1001b.  Then back at (1):

  ((1001b+100b-1)==1100b) & 1100b == 1100b

I.e. we got the same chachesize we had started with.  Hence infinite loop.

So the fix might be to change (2) to (more aggressive decline than 3/4)

  cachesize= (uint) ((long) cachesize*3/4 & (ulong) ~(min_cache - 1));

or simply (less aggressive decline)

  cachesize-= min_cache;
[1 Dec 2006 12:02] Tomash Brechko
Test script.

Attachment: bug24751.pl (application/octet-stream, text), 1.31 KiB.

[1 Dec 2006 22:06] Sveta Smirnova
Thank you for the report.

Verified as described using code analysis.
[10 Jan 2007 18:11] Tomash Brechko
Reviewed by e-mail.
[31 Jan 2007 19:11] Chad MILLER
Available in 4.1.23, 5.0.36, 5.1.15-beta.
[1 Feb 2007 1:38] Jon Stephens
Thank you for your bug report. This issue has been committed to our source repository of that product and will be incorporated into the next release.

If necessary, you can access the source repository and build the latest available version, including the bug fix. More information about accessing the source trees is available at

    http://dev.mysql.com/doc/en/installing-source.html

Documented as "If there was insufficient memory available to mysqld, this could sometimes cause the server to hang during startup" in 4.1.23, 5.0.36, and 5.1.15 changelogs. 

Please advise if my interpretation of this bug report was incorrect. Thanks!