2015-12-28 2 views
0

У меня серьезные проблемы с mysql с помощью pthreads. Я получаю ошибку после окончания моей программы:Mysql в многопоточной программе - my_thread_global_end()

«Ошибка в my_thread_global_end(): 1 нить не выходила»

я назвал mysql_library_init в основном, прежде чем начать любые темы. Ради этого я только начал 1 нить. После того, как поток закрыт (используя pthread_join), я вызываю mysql_library_end в main. В самом pthread я вызываю mysql_init. По какой-то причине это кажется неправильной причиной, я получаю ошибку. Я использую MySQL 5.6 и связываюсь с libmysqlclient.a.

Руководство MySQL крайне неясно и противоречиво, так что я надеюсь, что кто-то с логическим мышлением может объяснить мне:

«В nonmulti нарезки среды, mysql_init вызывает mysql_library_init автоматически по мере необходимости, однако, mysql_library_init есть. не поточно-безопасный в многопоточной среде, и, следовательно, ни один из них не является mysql_init. Перед вызовом mysql_init либо вызовите mysql_library_init до появления любых потоков, либо используйте мьютекс для защиты вызова mysql_library_init. Это должно быть сделано до любой другой клиентской библиотеки вызов."

Первая строка: Так mysql_init ТОЛЬКО вызывает mysql_library_init в NONmulti-резьбовым среде «когда это необходимо» (если это необходимо в любом случае в NONmulti-резьбовым среде?), И поэтому я могу conlcude из этого, что mysql_init() считает, что это НЕ требуется в многопоточной среде? Наверное, нет, так хорошо, я называю mysql_library_init в моей основной ... Затем я читаю везде, где я должен также вызвать mysql_init в потоке. Я хочу, чтобы каждый поток имел свое собственное соединение, так что отлично, я также делаю так, чтобы каждый поток имел свою собственную структуру MYSQL. Но руководство саис mysql_init не Потокобезопасная ... Эмм, хорошо ... Так что с 1 нить, я все еще есть проблемы ...

main -> mysql_library_init 
main -> create 1 pthread 
pthread -> mysql_init 
pthread -> mysql_real_connect 
pthread -> mysql_close 
.... 

жму Ctrl C через несколько секунд (MySQL был закрыто сейчас в потоке), так что чистка вверх начинает:

main -> pthread_cancel 
main -> pthread_join 
main -> mysql_library_end 

РЕЗУЛЬТАТ: Ошибка в my_thread_global_end: 1 нити не выход

........

+0

Я забыл упомянуть: поток все еще жив, когда я нажимаю Ctrl C, он блокирует семафор (для других целей) и прекратит блокировку, как только я нажму Ctrl C ... – Saskia

+0

Нет, я не , существует ли эта команда? Не можете найти его в онлайн-руководстве. Если вы предпочитаете, чтобы я вставлял код, я сделаю это. – Saskia

ответ

1
int main(void) 
{ 
    if (mysql_library_init(0, NULL, NULL) != 0) { ... } 
    if (mysql_thread_safe()) { ... } // This goes fine 

    sem_init(&queue.totalStored, 0, 0); 
    pthread_mutex_init(&mutex_bees, NULL); 
    pthread_create(&workerbees[tid], &attr, BeeWork, (void *) tid); 
    pthread_attr_destroy(&attr); 

    while (recv_signal == 0) 
    { 
     errno = 0; 
     sock_c = accept(sock_s, NULL, NULL); 

     if ((sock_c == -1) && (errno == EINTR)) 
     { 
     // do stuff 
     if (recv_signal == SIGHUP) { /* do stuff*/ } 
     } else { /* do stuff */ } 
    } 

    // CLEANUP 
    close(sock_s); 
    RC = pthread_cancel(workerbees[tid]); 
    if (RC != 0) { Log(L_ERR, "Unsuccessful pthread_cancel()"); } 

    // WAIT FOR THREADS TO FINISH WORK AND EXIT 
    RC = pthread_join(workerbees[tid], &res); 
    if (RC != 0) { Log(L_ERR, "Error: Unsuccessful pthread_join()"); } 

    if (res == PTHREAD_CANCELED) 
    { /* print debug stuff */ } 
    else { /* print debug stuff */ } 

    mysql_library_end(); 
    sem_destroy(&queue.totalStored); 
    exit(0); 
} 

void *BeeWork(void *t) 
{ 
    // DISABLE SIGNALS THAT main() ALREADY LISTENS TO 
    sigemptyset(&sigset); 
    sigaddset(&sigset, SIGINT); 
    sigaddset(&sigset, SIGTERM); 
    sigaddset(&sigset, SIGQUIT); 
    sigaddset(&sigset, SIGHUP); 
    pthread_sigmask(SIG_BLOCK, &sigset, NULL); 

    MYSQL *conn; 
    conn = mysql_init(NULL); 
    if (! mysql_real_connect(conn, server, prefs.mysql_user, prefs.mysql_pass, prefs.mysql_db, 0, prefs.mysql_sock, 0)) { /* error */ } 
    mysql_close(conn); 

    // Do stuff 
    ... 
    pthread_exit((void *) t); 
} 
1

Думаю, я могу ответить на свой вопрос, я выяснил, что мой обработчик очистки pthread не был выполнен (установлен с pthread_cleanup_push), а конец кода с pthread_exit был вызван раньше, чем main мог отменить поток. Я сделал pthread_cleanup_pop (0) и изменил его на pthread_cleanup_pop (1), поэтому обработчик очистки также был выполнен, когда поток выходит раньше, чем main может отменить. В этом обработчике очистки теперь mysql_thread_end действительно получил возможность запускать и устранить проблему.

Смежные вопросы