Bug #50565 NdbDictionary::getTable crashes in thread on utf8 tables
Submitted: 23 Jan 2010 13:57 Modified: 29 Jul 2016 0:31
Reporter: Stan Sawa Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Cluster: NDB API Severity:S3 (Non-critical)
Version:mysql-5.1-telco-7.0 OS:Linux
Assigned to: CPU Architecture:Any
Tags: 7.0.9
Triage: Triaged: D3 (Medium) / R6 (Needs Assessment) / E6 (Needs Assessment)

[23 Jan 2010 13:57] Stan Sawa
Description:
NdbDictionary::getTable crashes if certain conditions are met:
- table has nondefault charset (tested with utf8)
- this is first call to getTable() and is made in non-main thread
- mysqlcluster is installed somewhere else than /usr/local/mysql

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6348910 (LWP 23017)]
my_stat (path=0x7ffff6347700 "/usr/local/mysql/share/charsets/Index.xml", stat_area=0x7ffff6347640, my_flags=0) at my_lib.c:543

How to repeat:
make sure that file /usr/local/mysql/share/charsets/Index.xml doesn't exist (i just installed mysql cluster into /opt/mysql-cluster-gpl-7.0.9-linux-x86_64-glibc23/)

on mysql console:

mysql> CREATE TABLE test.foo ( c1 VARCHAR(15) NOT NULL) ENGINE=ndb CHARSET=utf8;

and minimal program trying to request information (error checking reduced to minimum):

#include <pthread.h>
#include <iostream>
#include <NdbApi.hpp>

extern "C" void *connect_and_fetch_dict(void *) {
    std::cout <<"preparing cluster connection ..." <<std::endl;
    Ndb_cluster_connection conn("127.0.0.1");
    if ( conn.connect(4, 5, 1) ) {
        std::cerr <<"cannot connect to mgmt node" <<std::endl;
        return NULL;
    }
    if ( conn.wait_until_ready(30, 0) < 0 ) {
        std::cerr <<"cluster not ready" <<std::endl;
        return NULL;
    }
    std::cout <<"connected to cluster" <<std::endl;
    Ndb db(&conn, "test");
    if ( db.init() ) {
        std::cerr <<"db.init(): " <<db.getNdbError().message <<std::endl;
        return NULL;
    }
    std::cout <<"got to test db" <<std::endl;
    NdbDictionary::Dictionary *dict = db.getDictionary();
    if ( dict == NULL ) {
        std::cerr <<"db.getDictionary(): " <<db.getNdbError().message <<std::endl;
        return NULL;
    }
    std::cout <<"got dictionary" <<std::endl;
    const NdbDictionary::Table *table = dict->getTable("foo");
    if ( table == NULL ) {
        std::cerr <<"dict->getTable(): " <<dict->getNdbError().message <<std::endl;
        return NULL;
    }
    std::cout <<"got table" <<std::endl;
    return NULL;
}

int main() {
    ndb_init();
    {
        pthread_t thid;
        pthread_create(&thid, NULL, connect_and_fetch_dict, NULL);
        pthread_join(thid, NULL);
    }
    ndb_end(0);
    return 0;
}

when run, this program will abort, and:
% gdb -c core ./ndb-dict-crash
....
...

Core was generated by `./ndb-dict-crash'.
Program terminated with signal 11, Segmentation fault.
#0  my_stat (path=0x7ffff6678700 "/usr/local/mysql/share/charsets/Index.xml", stat_area=0x7ffff6678640, my_flags=0) at my_lib.c:543

crashes can be stopped with:

% ln -s /opt/mysql-cluster-gpl-7.0.9-linux-x86_64-glibc23 /usr/local/mysql
(even creating empty file /usr/local/mysql/share/charsets/Index.xml helps)

or with forcing getTable to be called first in main thread.
[23 Jan 2010 15:34] Stan Sawa
full backtrace:
Program terminated with signal 11, Segmentation fault.
#0  my_stat (path=0x7ffff6678700 "/usr/local/mysql/share/charsets/Index.xml", stat_area=0x7ffff6678640, my_flags=0) at my_lib.c:543
543     my_lib.c: No such file or directory.
        in my_lib.c
(gdb) bt
#0  my_stat (path=0x7ffff6678700 "/usr/local/mysql/share/charsets/Index.xml", stat_area=0x7ffff6678640, my_flags=0) at my_lib.c:543
#1  0x00007ffff729558f in my_read_charset_file (filename=0x0, myflags=-160982496) at charset.c:337
#2  0x00007ffff7295842 in init_available_charsets (myflags=0) at charset.c:444
#3  0x00007ffff7295ae7 in get_charset (cs_number=33, flags=0) at charset.c:544
#4  0x00007ffff7251974 in NdbDictInterface::parseTableInfo (ret=0x7ffff6678dd0, data=<value optimized out>, len=<value optimized out>, fullyQualifiedNames=<value optimized out>, version=<value optimized out>)
    at NdbDictionaryImpl.cpp:2694
#5  0x00007ffff72524d8 in NdbDictInterface::getTable (this=0x61aae0, signal=<value optimized out>, ptr=<value optimized out>, noOfSections=<value optimized out>, fullyQualifiedNames=69)
    at ../../../../storage/ndb/include/util/UtilBuffer.hpp:95
#6  0x00007ffff7252753 in NdbDictInterface::getTable (this=0x61aae0, name=<value optimized out>, fullyQualifiedNames=32) at NdbDictionaryImpl.cpp:2346
#7  0x00007ffff7252be2 in NdbDictionaryImpl::fetchGlobalTableImplRef (this=0x61a848, obj=...) at NdbDictionaryImpl.cpp:1796
#8  0x00007ffff723dbae in NdbDictionaryImpl::getTable (this=<value optimized out>, name=<value optimized out>, data=0x0) at NdbDictionaryImpl.hpp:1208
#9  NdbDictionary::Dictionary::getTable (this=<value optimized out>, name=<value optimized out>, data=0x0) at NdbDictionary.cpp:2114
#10 0x0000000000401497 in connect_and_fetch_dict () at dict-init-problem.cc:43
#11 0x00007ffff79c373a in start_thread (arg=<value optimized out>) at pthread_create.c:300
#12 0x00007ffff67456dd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#13 0x0000000000000000 in ?? ()
Current language:  auto
The current source language is "auto; currently c".
(gdb)
[13 Dec 2011 23:39] Daniel Smythe
Verified as described