Bug 462534

Summary: SQL Config files should not be read more than once
Product: Red Hat Enterprise Linux 5 Reporter: Bryan Mason <nobody+bjmason>
Component: mysqlAssignee: Tom Lane <tgl>
Status: CLOSED ERRATA QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 5.2CC: bmason, byte, hhorak, kvolny, patrickm, sghosh, tao
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-09-02 09:45:54 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Proposed patch none

Description Bryan Mason 2008-09-16 22:25:48 UTC
Description of problem:

    Customer reports that his /etc/my.conf file is being read twice.

    Because of the double-loading /etc/my.cnf file, every time MySQL
    restarts the relay file changes and is not an actual file in the
    /var/run/mysqld directory, nor is it anywhere near numerical
    order.

    Here is the problem it causes -

        mysql>
        show slave statusG
        *************************** 1. row *************************** [...]
        Relay_Log_File: mysqld-relay-bin.000023
        Relay_Log_Pos: 185588730
        Relay_Master_Log_File: mysql-bin.000044
        Slave_IO_Running: No
        Slave_SQL_Running: No
        Replicate_Do_DB: cdr,weboffice,cdr,weboffice
        Replicate_Ignore_DB:
        [...]
        1 row in set (0.00 sec)

    and the /var/log/mysqld.log file shows repeated instances of:

        080903 15:11:59 [ERROR] Could not find target log during relay log
        initialization
        080903 15:11:59 [ERROR] Failed to initialize the master info structure

Version-Release number of selected component (if applicable):

    mysql-5.0.45-7.el5

How reproducible:

    Every time

Steps to Reproduce:

    1. service mysqld start

or

    1.  strace -o mysqld-strace.log /usr/libexec/mysqld --basedir=/usr \
        --datadir=/var/lib/mysql --user=mysql \
        --pid-file=/var/run/mysqld/mysqld.pid --skip-external-locking \
        --socket=/var/lib/mysql/mysql.sock &
  
Actual results:

    /etc/my.cnf is read twice, as evidenced by the following section
    of mysqld-strace.log:

        uname({sys="Linux", node="why-it218594.usersys.redhat.com", ...}) = 0
        stat("/etc/my.cnf", {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
        open("/etc/my.cnf", O_RDONLY)           = 3
        fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
        mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 
        -1, 0) = 0x2b1bbde23000
        read(3, "[mysqld]ndatadir=/var/lib/mysqln"..., 4096) = 310
        read(3, "", 4096)                       = 0
        close(3)                                = 0
        munmap(0x2b1bbde23000, 4096)            = 0
        stat("/root/.my.cnf", 0x7fffecc9ba60)   = -1 ENOENT (No such file or
        directory)
        stat("/etc/my.cnf", {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
        open("/etc/my.cnf", O_RDONLY)           = 3
        fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
        mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 
        -1, 0) = 0x2b1bbde23000
        read(3, "[mysqld]ndatadir=/var/lib/mysqln"..., 4096) = 310
        read(3, "", 4096)                       = 0
        close(3)                                = 0
        munmap(0x2b1bbde23000, 4096)            = 0
        lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
        getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0

Expected results:

    /etc/my.cnf should only be read once.

Additional info:

    This bug is documented in http://bugs.mysql.com/bug.php?id=20748
    "Bug#20748 SQL Config files should not be read more than once"

Comment 1 Bryan Mason 2008-09-16 22:27:29 UTC
Created attachment 316912 [details]
Proposed patch

Adapted from upstream mysql-5.0.67

Comment 4 Issue Tracker 2008-09-19 19:55:25 UTC
Hi Dave,

The backport was from the latest version of MySQL (version 5.0.67).  The
change was made to init_default_directories(), which is called by
init_defaults(), which is called by a lot of different fiels within the
MySQL codebase.  It's probably used by the various MySQL programs to load
the MySQL configuration files.

Since this was taken from a released version of MySQL, it presumably has
already undergone code review and some amount of testing by the upstream
MySQL community.

The root cause of the problem is that init_default_directories() loads the
default_directories array with the /etc directory twice.  Once as "/etc/"
and then once as DEFAULT_SYSCONFDIR (which is #defined to "/etc").  After
init_default_directories() is called, default_directories looks like:

    (gdb) print default_directories
    $3 = {0x932f84 "/etc/", 0x8f8ea8 "", 0x932f95 "~/", 0x932f98 "/etc",
0x0,
    0x0, 0x0, 0x0}

The main thing that the proposed patch does is to modify
init_default_directories() so that each directories are added by
add_directory().  add_directory() first calls normalize_dirname() to
change "/etc" into "/etc/", and then calls array_append_string_unique() to
add the directory onto the default_directories array only if the directory
doesn't already exist in the array.  That way, /etc isn't added since
/etc/ is already in the array.  With the new code, default_directories
looks like:

    (gdb) print default_directories[0]
    $1 = 0x10832a88 "/etc/"
    (gdb) print default_directories[1]
    $2 = 0x10832a90 ""
    (gdb) print default_directories[2]
    $3 = 0x10832a98 "~/"
    (gdb) print default_directories[3]
    $4 = 0x0
    (gdb) print default_directories[4]
    $5 = 0x0
    (gdb) print default_directories[5]
    $6 = 0x0
    (gdb) print default_directories[6]
    $7 = 0x0
    (gdb) print default_directories[7]
    $8 = 0x0

There may be an simpler way to work around this problem in RHEL.  The bit
of code where /etc is double-entered into the default_directories array is
here (I've snipped all the bits of code that would be #ifdef'd out for
RHEL:

    static void init_default_directories()
    {
      const char *env, **ptr= default_directories;
    
       #ifdef __WIN__
       [...]
       #elif defined(__NETWARE__)
        [...]
       #else
       #if defined(__EMX__) || defined(OS2)
       [...]
       #endif
[1]      *ptr++= "/etc/";
       #endif
         if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
           *ptr++= env;
         *ptr++= "";                   /* Place for defaults_extra_file
*/
       #if !defined(__WIN__) && !defined(__NETWARE__)
         *ptr++= "~/";;
       #elif defined(__WIN__)
       [...]
       #endif
       #ifdef DEFAULT_SYSCONFDIR
         if (DEFAULT_SYSCONFDIR != "")
[2]        *ptr++= DEFAULT_SYSCONFDIR;
       #endif
         *ptr= 0;                      /* end marker */
       }

If we were to comment out either the first bit of code[1] that adds
"/etc/" to the default_directories array or the bit of code[2] that adds
DEFAULT_SYSCONFDIR to the default_directories array, that would achieve
the same purpose with only a couple of changed lines -- much less
invasive, although more from upstream.

~ Bryan


This event sent from IssueTracker by dmaley 
 issue 218594

Comment 5 Issue Tracker 2008-09-19 19:55:27 UTC
One other note.  There's a _much_ simpler way to test that this issue has
been fixed.  Running "/usr/libexec/mysqld --help --verbose" lists the
default directories.  The version already in RHEL reports:

    # rpm -q mysql-server
    mysql-server-5.0.45-7.el5.x86_64
    # /usr/libexec/mysqld --help --verbose | grep --after=1 '^Default
options'
    Default options are read from the following files in the given order:
    /etc/my.cnf ~/.my.cnf /etc/my.cnf 

After applying the proposed patch, mysqld reports:

    # rpm -q mysql-servermysql-server-5.0.45-7.it218594.5.el5.x86_64
    # /usr/libexec/mysqld --help --verbose | grep --after=1 '^Default
options'
    Default options are read from the following files in the given order:
    /etc/my.cnf ~/.my.cnf 

~ Bryan








This event sent from IssueTracker by dmaley 
 issue 218594

Comment 17 errata-xmlrpc 2009-09-02 09:45:54 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2009-1289.html