Hi, I'm new to embedding and also to GTK, so it's very likely that I'm
misssing something quite obvious here, I apologize in advance if that's the
case, I also apologize for the long post, but I wanted to include
everything I think could be relevant.

Scenario:
I'm trying to embed Gecko into a C application that uses extensive
multithreading, the general idea is that once the gtkmozembed widget is
running, it can be controlled from a separated thread (i.e load a different
url, reload, etc.)

Problem:
So far I've been able to embed gtkmozembed into the application, trouble is
that when the first call is made to any function that receives the
gtkmozembed widget as a parameter i.e:
gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), "http://www.yahoo.com";);
from a different thread that the one that created the widget, I get a SIGSEV
crash.

Debug:
I tried to debug the issue, and so far I found that it's not GTK related,
because I can control the main window widget from other threads without any
trouble. It seems that the pointer to the gtkmozembed widget is NULL right
after calling gtk_main(). To further test the behavior I replaced the
threads with a timed event inside a loop that calls 
gtk_main_iteration_do(FALSE), instead of using gtk_main(). This does work,
so it may indicate that the issue is related to gtkmozembed and threads.
I've have tried using pthreads in the usual way, and also gthreads of glib,
with the same result.

Questions:
I'm I missing something obvious here ?, Is there any special considerations
that need to be taken into account when using gtkmozembed widget in a
multithread application ?

Versions:
Tested in 2 different platforms:
FC3: 2.6.12-1.1381_FC3smp
gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)
glibc-2.3.6-0.fc3.1
gtk2-2.4.14-4.fc3.3
glib2-2.4.8-1.fc3
mozilla-1.7.12-1.3.1
mozilla-devel-1.7.12-1.3.1
mozilla-nspr-1.7.12-1.3.1
mozilla-nspr-devel-1.7.12-1.3.1 
mozilla-nss-devel-1.7.12-1.3.1
mozilla-nss-1.7.12-1.3.1

FC5:2.6.19-1.2288.fc5smp
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)
glibc-2.4.90-15
glib2-2.10.3-1
gtk2-2.8.20-1
mozilla-1.7.13-1.1.fc5
mozilla-devel-1.7.13-1.1.fc5

Any suggestions will be highly appreciated, thanks in advance.

Dante

============================= test case ============================= 
/* test_mozembed.cpp
 * Should display a browser window, and after 5 secs will move the window 
to a different 
 * position, and after 10 secs should load a different url.
 * 
 * By defining DONT_USE_THREADS threads and gtk_main() are not used, and
 the programm runs ok
 * when DONT_USE_THREADS is undefined threads and gtk_main() are used and
 the programm crahses
 * 
 * compiled with:
 * g++ -ggdb3 -o test_mozembed{,.cpp} \
 *       -I/usr/include/mozilla-1.7.13 \
 *       -I/usr/include/mozilla-1.7.13/xpcom \
 *       -I/usr/include/mozilla-1.7.13/gtkembedmoz \
 *       -L/usr/lib/mozilla-1.7.13 \
 *       -I/usr/include/nspr4 \
 *       -lgtkembedmoz \
 *       `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>

#include <gtk/gtk.h>
#include <glib.h>
#include <gtkmozembed.h>

//#define DONT_USE_THREADS

void *thread1(void *pv_Param);
void *thread2(void *pv_Param);
gint event_delete(GtkWidget *gtkwidget, GdkEvent *gdkevent, gpointer param);
void event_destroy(GtkWidget *gtkwidget, gpointer param);

GtkWidget *mainwin,
                  *vbox,
                  *mozembed;
                  
int end;

int signalid[2];

GThread *gthread1,
                *gthread2; 

GError *err1 = NULL,
           *err2 = NULL;

int main(int argc, char *argv[])
{
        int     executed1,
                executed2;
                
        time_t start1,
                   elapsed1,
                   start2,
                   elapsed2;
                   
        gtk_init(&argc, (char ***)(&argv));

#ifndef DONT_USE_THREADS       
        if(!g_thread_supported())  {
                g_thread_init(NULL);
                gdk_threads_init();
                printf("main: g_thread supported\n");
        }
        else  {
                printf("main: g_thread NOT supported\n");
        }
#endif

        gtk_moz_embed_set_profile_path(".", "mozembed");

        if((mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL)) == NULL) {
                printf("main: Creating main window\n");
                exit(1);
        }
        printf("main: Main window created ok\n");

        gtk_widget_set_usize(mainwin, 800, 600);
        gtk_window_resize(GTK_WINDOW(mainwin), 800, 600);
        gtk_window_move(GTK_WINDOW(mainwin), 100, 100);

        if((vbox = gtk_vbox_new(FALSE, 0)) == NULL) {
                printf("main: Creating vertical box\n");
                exit(1);
        }
        printf("main: Vertical box created ok\n");

        gtk_window_set_decorated(GTK_WINDOW(mainwin), TRUE);
        gtk_window_set_resizable(GTK_WINDOW(mainwin), TRUE);
        gtk_window_set_title(GTK_WINDOW(mainwin), "Test");

        if((mozembed = gtk_moz_embed_new()) == NULL) {
                printf("main: Creating mozilla widget\n");
                exit(1);
        }
        printf("main: Mozilla widget box created ok\n");

        gtk_box_pack_start(GTK_BOX(vbox), mozembed, TRUE, TRUE, 0);
        gtk_container_add(GTK_CONTAINER(mainwin), vbox);

        signalid[0] = g_signal_connect(G_OBJECT(mainwin), "delete_event",
                 G_CALLBACK(event_delete), NULL);
        signalid[1] = g_signal_connect(G_OBJECT(mainwin), "destroy",
                 G_CALLBACK(event_destroy), NULL);

        printf("main: Browser created ok\n");
        
        gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), 
                "http://www.google.com";);
        printf("main: Loading url http://www.google.com\n";);
        
        gtk_widget_show(mozembed);
        gtk_widget_show(vbox);
        gtk_widget_show(mainwin);

#ifndef DONT_USE_THREADS       
        if((gthread1 = g_thread_create((GThreadFunc)thread1, 
           NULL, TRUE, &err1)) == NULL) {
                printf("main: Thread create failed: %s!!\n",
err1->message );
                g_error_free(err1) ;
        }
        printf("main: gthread1 created ok\n");
        
        if((gthread2 = g_thread_create((GThreadFunc)thread2, 
          NULL, TRUE, &err2)) == NULL) {
                printf("main: Thread create failed: %s!!\n",
err2->message );
                g_error_free(err2) ;
        }
        printf("main: gthread2 created ok\n");
#endif
        
        printf("main: Entering gtk main loop\n");
        
        /* dirty workaround, just to test if the trouble doest't 
         * happend when not using threads and gtk_main() 
         */
#ifdef DONT_USE_THREADS        
        end = FALSE;
        executed1 = FALSE;
        start1 = start2 = time(NULL);
        executed2 = FALSE;
        while(!end) {
                gtk_main_iteration_do(FALSE);
                elapsed1 = time(NULL) - start1;
                if(!executed1 && elapsed1 >= 10) {
                        printf("main: Loading http://www.yahoo.com\n";);
                        gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), 
                                "http://www.yahoo.com";);
                        executed1 = TRUE;
                }
                elapsed2 = time(NULL) - start2;
                if(!executed2 && elapsed2 >= 5) {
                        printf("main: Moving window\n");
                        gtk_window_move(GTK_WINDOW(mainwin), 200, 200);
                        executed2 = TRUE;
                }
                
        }
#else   
        gtk_main();
#endif  

        return(0);
}

void *thread1(void *param)
{
        printf("thread1: Waiting...\n");
        sleep(10);
        printf("thread1: Loading http://www.yahoo.com\n";);
        gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), 
                "http://www.yahoo.com";);
        printf("thread1: Ending\n");
        
        return(NULL);
}

void *thread2(void *param)
{
        printf("thread2: Waiting...\n");
        sleep(20);
        printf("thread2: Moving window\n");
        gtk_window_move(GTK_WINDOW(mainwin), 200, 200);
        printf("thread2: Ending\n");
        
        return(NULL);
}

gint event_delete(GtkWidget *gtkwidget, GdkEvent *gdkevent, gpointer param)
{
        printf("Delete event\n");
        return(FALSE);
}

void event_destroy(GtkWidget *gtkwidget, gpointer param)
{
        end = TRUE;
        gtk_main_quit();
        gtk_exit(FALSE);
        printf("Destroy event\n");
}

============================= gdb session ============================= 
(gdb) run
Starting program: /home/gtrevize/workspace/tbx/test/tst_browser1_d
Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0xb25000
[Thread debugging using libthread_db enabled]
[New Thread -1208390976 (LWP 1835)]
main: g_thread supported
main: Main window created ok
main: Vertical box created ok
[New Thread 33373088 (LWP 1838)]
main: Mozilla widget box created ok
main: Browser created ok
main: Loading url http://www.google.com
Detaching after fork from child process 1839.
[New Thread 145013664 (LWP 1841)]
[New Thread -1222644832 (LWP 1843)]
[New Thread -1212154976 (LWP 1842)]
main: gthread1 created ok
[New Thread -1233134688 (LWP 1844)]
main: gthread2 created ok
main: Entering gtk main loop
thread1: Waiting...
thread2: Waiting...
[New Thread -1243624544 (LWP 1845)]
[New Thread -1254114400 (LWP 1846)]
thread1: Loading http://www.yahoo.com

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1212154976 (LWP 1842)]
0x00ec9984 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
(gdb) backtrace
#0  0x00ec9984 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
#1  0x00ec9a7a in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
#2  0x00ec98ec in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
#3  0x020adaf7 in nsCOMPtr_base::~nsCOMPtr_base$base ()
from /usr/lib/mozilla-1.7.13/libxpcom.so
#4  0x00f59d72 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
#5  0x00f5dc00 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libnecko.so
#6  0x04caa476 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#7  0x04caaba1 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#8  0x04c84302 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#9  0x04c8e619 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#10 0x04c966c9 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#11 0x04c8f96c in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#12 0x04c8c562 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libdocshell.so
#13 0x00834b33 in NSGetModule ()
from /usr/lib/mozilla-1.7.13/components/libwebbrwsr.so
#14 0x0032f388 in EmbedPrivate::LoadCurrentURI ()
from /usr/lib/mozilla-1.7.13/libgtkembedmoz.so
#15 0x0032b034 in gtk_moz_embed_load_url ()
from /usr/lib/mozilla-1.7.13/libgtkembedmoz.so
#16 0x0804904e in thread1 (param=0x0) at tst_browser1.cpp:153
#17 0x0048c9ff in g_thread_create_full () from /usr/lib/libglib-2.0.so.0
#18 0x00c2dfb5 in start_thread () from /lib/libpthread.so.0
#19 0x00a5abae in clone () from /lib/libc.so.6

================== valgrind output (partial) ================== 
Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0x0
    at 0x4A1C984: (within /usr/lib/mozilla-1.7.13/components/libnecko.so)
    by 0x4A1CA79: (within /usr/lib/mozilla-1.7.13/components/libnecko.so)
    by 0x4A1C8EB: (within /usr/lib/mozilla-1.7.13/components/libnecko.so)
    by 0x20ADAF6: nsCOMPtr_base::~nsCOMPtr_base()
(in /usr/lib/mozilla-1.7.13/libxpcom.so)
    by 0x4AACD71: (within /usr/lib/mozilla-1.7.13/components/libnecko.so)
    by 0x4AB0BFF: (within /usr/lib/mozilla-1.7.13/components/libnecko.so)
    by 0x53BE475: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)
    by 0x53BEBA0: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)
    by 0x5398301: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)
    by 0x53A2618: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)
    by 0x53AA6C8: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)
    by 0x53A396B: (within /usr/lib/mozilla-1.7.13/components/libdocshell.so)

_______________________________________________
dev-embedding mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-embedding

Reply via email to