libmysqlclient + threads + gdb = ?
От: green.nsk  
Дата: 13.08.12 21:28
Оценка:
Если вкратце, многоуважаемый Олл, есть примерно такой кусов кода (см. ниже). Все вроде бы работает (пишем под линукс), но с с некоторых пор (с каких пор, к сожалению, выяснить не удалось -- произошел какой-то апдейт дебиана или что-то изменилось в нашем коде), стал ломаться вызов mysql_real_connect -- стал возвращать NULL некоторых тредах. При этом, если connect завершается успешно, то обычно первый же запрос говорит "server has gone away during query". Самое неприятное, что происходит это только если запустить программу под дебаггером -- при запуске без дебаггера все работает достаточно надежно.

При этом, если раскомментировать строку с usleep, то проблема исчезает — все опять начинает работать очень хорошо, как под дебаггером, так и без него. Такое решение, конечно, не устраивает, хочется докопаться до проблемы. Думал запостить баг в mysql, но решил сначала попросить коллективный разум посмотреть на этот код -- может быть чужие глаза лучше найдут проблему (или даже кто-то захочет поэкспериментировать на своей конфигурации).

У нас все работает на Debian Squeeze + Percona Server 5.5 (хотя, как я понимаю, сервер тут совершенно ни при чем). Компилировал как с библиотеками из поставки Percona, так и с теми, что идут в дебиане — разницы ровно никакой.

Спасибо всем
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#include <mysql.h>

void* thread(void*)
{
    my_bool mbRet = mysql_thread_init();
    assert(mbRet == 0); // weird, but as per mysql_thread_init documentation

    MYSQL sqlObj;
    void* pRet = mysql_init(&sqlObj);
    assert(pRet == &sqlObj);
    pRet = mysql_real_connect(&sqlObj, "127.0.0.1", "root", "123", "mysql", 3306, "/var/run/mysqld/mysqld.sock", 0);
    assert(pRet == &sqlObj);  // ломается тут.
    mysql_close(&sqlObj);

    mysql_thread_end();

    return NULL;
}

int main()
{
    assert(mysql_thread_safe());

    static const size_t nThreads = 10;

    pthread_t threads[nThreads];
    for (size_t i = 0; i < nThreads; ++i)
    {
        int iRet = pthread_create(&threads[i], NULL, thread, NULL);
        //usleep(10000);
        assert(iRet == 0);
    }

    for (size_t i = 0; i < nThreads; ++i)
    {
        void* retVal = NULL;
        pthread_join(threads[i], &retVal);
        assert(retVal == NULL);
    }

    return 0;
}

// compile: g++ a.cpp -ggdb -lpthread -lmysqlclient_r && gdb ./a.out
mysql libmysql threads pthread gdb
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.