[Evolution-hackers] Hang in e_book_new when multiple threads are involved



I was told by Muelli over IRC that I should post this to the hackers list.

In some of the code I'm writing for Mozilla, I noticed that one set of circumstances caused the code to hang in e_book_new. When I run the e_book_new in a brand new thread under the testing environment, the code would just hang. If I did it under regular UI environment or ran it in the same thread, the hang disappeared. I am currently using the 2.24 version of Evolution that is provided under Debian testing.

Here is some code that demonstrates the problem (a rather small test case mimicking the conditions):
#include <libebook/e-book.h>
#include <libedataserver/e-source-list.h>
#include <pthread.h>
#include <iostream>

using namespace std;

void *handle_source(void *source);

ESourceList *sources;
int main() {
   g_type_init();
   GConfClient *gconf = gconf_client_get_default();
sources = e_source_list_new_for_gconf(gconf, "/apps/evolution/addressbook/sources");
   GSList *groups = e_source_list_peek_groups(sources);
   char *uid = NULL;
   for (;groups;groups = groups->next) {
       ESourceGroup *group = E_SOURCE_GROUP(groups->data);
       if (!group) continue;

       GSList *sources = e_source_group_peek_sources(group);
       for (; sources; sources = sources->next) {
           ESource *source = E_SOURCE(sources->data);
           uid = (char *)e_source_peek_uid(source);
           goto end;
       }
   }
end:
   pthread_attr_t threadAttrs;
   pthread_attr_init(&threadAttrs);
   pthread_t thread;
   pthread_create(&thread, &threadAttrs, handle_source, uid);
   pthread_join(thread, NULL);
}

void *handle_source(void *source2) {
ESource *source = e_source_list_peek_source_by_uid(sources, (const char *)source2);
   cout << "Before new\n";
   EBook *book = e_book_new(source, NULL);
   cout << "After new\n";
   if (!e_book_open(book, true, NULL)) {
       return (void*)1;
   }

   GList *contacts;
if (!e_book_get_contacts(book, e_book_query_any_field_contains(""), &contacts, NULL)) {
       cout << "Can't get contacts!\n";
   }

   cout << g_list_length(contacts) << endl;
   return 0;
}

jcranmer quetzalcoatal ~/evolution $ make
g++ -g -o evolution-test -I/usr/include/evolution-data-server-2.24 -I/usr/include/evolution-data-server-2.24 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2 -I/usr/include/gconf/2 -I/usr/include/glib-2.0 -ledataserver-1.2 -lebook-1.2 -pthread test2.cpp
jcranmer quetzalcoatl ~/evolution $ ./evolution-test
Before new


If you change the pthread code to directly call handle_source(uid), you get the expected results:
jcranmer quetzalcoatl ~/evolution $ ./evolution-test
Before new
After new
1

Hopefully, this should be enough information to have other people reproduce the issue.

--
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]