views:

267

answers:

2

I have written a simple multi-threaded C program to access MySQL,it works fine except when i add usleep() or sleep() function in each thread function. i created two pthreads in the main method,

int main(){
        mysql_library_init(0,NULL,NULL);
        printf("Hello world!\n");
        init_pool(&p,100);
        pthread_t producer;
        pthread_t consumer_1;
        pthread_t consumer_2;
        pthread_create(&producer,NULL,produce_fun,NULL);
        pthread_create(&consumer_1,NULL,consume_fun,NULL);
        pthread_create(&consumer_2,NULL,consume_fun,NULL);
        mysql_library_end();
}



   void * produce_fun(void *arg){
    pthread_detach(pthread_self());
    //procedure
    while(1){
        usleep(500000);
        printf("producer...\n");
        produce(&p,cnt++);
    }
    pthread_exit(NULL);
}

void * consume_fun(void *arg){
    pthread_detach(pthread_self());
    MYSQL db;
    MYSQL *ptr_db=mysql_init(&db);
    mysql_real_connect();

    //procedure
    while(1){
        usleep(1000000);
        printf("consumer...");
        int item=consume(&p);
        addRecord_d(ptr_db,"test",item);
    }
    mysql_thread_end();
    pthread_exit(NULL);
}

void addRecord_d(MYSQL *ptr_db,const char *t_name,int item){
    char query_buffer[100];
    sprintf(query_buffer,"insert into %s values(0,%d)",t_name,item);
//pthread_mutex_lock(&db_t_lock);
    int ret=mysql_query(ptr_db,query_buffer);
    if(ret){
        fprintf(stderr,"%s%s\n","cannot add record to ",t_name);
        return;
    }

    unsigned long long update_id=mysql_insert_id(ptr_db);
//    pthread_mutex_unlock(&db_t_lock);
    printf("add record (%llu,%d) ok.",update_id,item);
}

the program output errors like:

[Thread debugging using libthread_db enabled]
[New Thread 0xb7ae3b70 (LWP 7712)]
Hello world!
[New Thread 0xb72d6b70 (LWP 7713)]
[New Thread 0xb6ad5b70 (LWP 7714)]
[New Thread 0xb62d4b70 (LWP 7715)]
[Thread 0xb7ae3b70 (LWP 7712) exited]
producer...
producer...
consumer...consumer...add record (31441,0) ok.add record (31442,1) ok.producer...
producer...
consumer...consumer...add record (31443,2) ok.add record (31444,3) ok.producer...
producer...
consumer...consumer...add record (31445,4) ok.add record (31446,5) ok.producer...
producer...
consumer...consumer...add record (31447,6) ok.add record (31448,7) ok.producer...
Error in my_thread_global_end(): 2 threads didn't exit
[Thread 0xb72d6b70 (LWP 7713) exited]
[Thread 0xb6ad5b70 (LWP 7714) exited]
[Thread 0xb62d4b70 (LWP 7715) exited]

Program exited normally.

and when i add pthread_mutex_lock in function addRecord_d,the error still exists. So what exactly the problem is?

A: 

While your producer and consumer threads sleep, they're holding onto the mysql connections which are open for the duration of the respective functions.

When the program tries to end, chances are those threads are sleeping and can not receive the termination signal. Hence the error from my_thread_global_end().

I don't have access to a dev environment right now, so I can't try your sample. But I think this may get past the error, although it would be a highly inefficient code (sample from consume_fun function):

//procedure
while(1){
    usleep(1000000);

    MYSQL *ptr_db=mysql_init(&db);
    mysql_real_connect();

    printf("consumer...");
    int item=consume(&p);
    addRecord_d(ptr_db,"test",item);

    mysql_thread_end();
}

In a nutshell, the above sample should force the connection to be established and closed outside of the sleep cycle. I don't think this is the best code, but for the purposes of your illustration, this should get rid of the errors.

Keep in mind: this will force you to open and close connections in a loop, which would be a highly inefficient use of resources in a 'production' type environment, so don't do it in real life. :)

Hope this helps.

Mike Mytkowski
Hi Mike,thanks for your help.When I replace the corresponding code with those you supplied above,Four threads are created and exists soon,the output is just "hello world".so I think there may be some error in the main method,really,i forgot to add the join method,so I run the risk of terminating the main method while other three threads are still alive.Add pthread_join() to the end of the main method,the error won't occur anymore.Well,I am new to multi-thread programming,and your reply reminds me of the join method, thanks.
A: 

The problem is that you are calling mysql_library_end() too early (especially with the usleep() in the threads). It is possible to finish the main thread and have the other threads continue to do work, but it is not recommended. Your solution to add the pthread_join() is the best. You could also eliminate the mysql_library_end() and it will work.