Bug #4451 MySQL is not working when compiled with GCC 3.4.1
Submitted: 8 Jul 2004 3:02 Modified: 8 Jul 2004 16:05
Reporter: Konstantin Osipov (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:4.1.*, 5.0.* OS:
Assigned to: Jani Tolonen CPU Architecture:Any

[8 Jul 2004 3:02] Konstantin Osipov
Description:
When compiled with gcc 3.4.1 MySQL 4.1 or 5.0 prints the following on start up:
kostja@oak:~/mysql/mysql-4.1-root> sql/mysqld
040708  4:42:59  Warning: setrlimit could not change the size of core files to 'infinity';  We may not be able to generate a core file on signals
mysqld: mf_keycache.c:295: init_key_cache: Assertion `key_cache_block_size >= 512' failed.
mysqld got signal 6;
<cut>

The assertion in init_key_cache fails because key_cache_block_size argument is 0.
This argument is taken from default key cache variable, which is supposed to be 
initialized along with dflt_key_cache.
To be more precise, we've got the following calling sequence:
main
-> init_common_variables
       -> mysql_init_variables
            -> get_or_create_key_cache
                 -> create_key_cache
This one creates a key cache and partially initializes it from global dflt_key_cache_var.
As dflt_key_cache_var is not initizlied yet key_cache->param_block_size gets assigned 0.

Few lines later init_common_variables calls get_options, which in calls init_variables 
to init dflt_key_cache_var and all created so far key cache variables with default
values. (I wonder why key cache creation is so compliacated)

This is done by means of the follo  
if (options->var_type & GET_ASK_ADDR &&
        (variable= (*getopt_get_addr)("", 0, options)))
      init_one_value(options, variable, options->def_value);
wing check in mysys/my_getopt.c:

where options->var_type is of type enum get_opt_var_type
The problem is that this check is never true when compiled with gcc-3.4.1.
Despite that var_type is initialized with mask of (GET_ULONG | GET_ASK_ADDR),
it never gets combination of this values, only the first one.
In other words, as GET_ASK_ADDR is not in enum get_opt_var_type its value is never
assigned to var_type.

This is a simple test to of the  problem:
kostja@oak:~> cat foo.cc
#include <stdio.h>
int main()
{
  enum my_enum { ULONG= 1, DUMMY=2 };
  my_enum e= (my_enum) (ULONG | 128);
  printf("%d\n", (unsigned) e);
}
kostja@oak:~> g++ foo.cc; ./a.out
1
kostja@oak:~> 

It turns out that such behaviour is 100% standard, which says:

An expression of arithmetic or enumeration type can be converted to enumeration type 
explicitly. The value is unchanged if it is in the range of enumeration type; otherwise 
the resulting enumeration value is unspecified.

Indeed, all earlier versions of gcc would print here 129, as does gcc 3.3.1:
kostja@oak:~> /usr/bin/g++ foo.cc;./a.out 
129

How to repeat:
Compile with 3.4.1 and run

Suggested fix:
change type of my_options::var_type to ulong.
Check the rest of variables which accept bitmask of enum values to be of type ulong.
[8 Jul 2004 12:23] Konstantin Osipov
This bug only shows up when compiled with debug.
Optimized version keeps using integer arithmetic.
[8 Jul 2004 16:05] Jani Tolonen
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 bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html