Glib 2.32.x, Win32 and threading



Hi,

Bit long, sorry.

I build my own GTK+ stack with MinGW (TDM-4.6.1) and have been using 2.16 and Glib 2.28 (with Gtk2-Perl bindings mostly) for a long time, then switched to GTK+ 2.24 when that started to get stable enough. Wanting to start with WebKit I switched to Glib 2.30 to be able to use GObject-Introspection from Dieter's git repo.

This still worked fine, but needing later G-O-I interfaces from WebKit, I tried to build 1.8 which needs Glib 2.31 or later, so I switched to Glib 2.32.3, and this is where my problems started.

All threaded Gtk2-Perl apps locked up on startup and I initially thought it was a Gtk2-Perl problem, but building the example from the FAQ:

http://developer.gnome.org/gtk-faq/stable/x481.html

result in the same problem. The easiest way to reproduce it is to start the example and then move the window which immediately results in a deadlock.

Searching around, I saw mention of GTK+ 2.24 being frozen at Glib 2.28, so I built GTK+ 3.4.3 and then the example against it, but it does exactly the same. I tried with Ruben's MinGW-x64 builds, but same thing.

Searching some more, I found references of different threads on Windows updating the same window can have problems (for Gtk2-Perl this is anyhow a no-no, so I never do that), I moved updating the label outside the threads via g_idle_add() (see attached gtk-thread.c), but still the same result.

Looking at the changes between Glib 2.30 and 2.32, I saw the threading was reworked, and as I was testing on Windows 7, I thought it could be the NT 6.0 or later primitives being used, and tried with Windows XP, but this triggered the assertion:

-----
Glib:ERROR:glib-2.32.3\glib\gthread-win32.c:639:g_thread_xp_AcquireSRWLockExclusive: assertion failed: (!lock->writer_locked)
-----

Basically:

-----
  /* CRITICAL_SECTION is reentrant, but SRWLock is not.
   * Detect the deadlock that would occur on later Windows version.
   */
  g_assert (!lock->writer_locked);
-----

With previous Glib versions, GMutex on Win32 was implemented with EnterCriticalSection() and friends, and taking a lock twice in the same thread did not cause any issues, for example:

-----
  gdk_threads_enter();
  gdk_threads_enter();
-----

would work fine, but with the new code, it either aborts or deadlocks.

As I am not that closely familiar with all the inner workings, and what was intended, I am not sure if this is supposed to be, but that change currently with even GTK+ 3.4 makes Glib 2.32 unusable on Windows, so I tried to debug further.

Unable to get decent backtraces with GDB, I rebuild the whole stack with VS2010 and although I could actually get the backtrace of where the deadlock is taking place, it still was unclear where the first lock was taken. I added the code in  gdk_threads_enter() and gdk_threads_leave to print below info, basically:
- for gdk_threads_enter():
  - print the function name and current thread pointer
  - print "deadlock" if the lock is already held
  - print the backtrace
- for gdk_threads_leave()
  - print the function name and current thread pointer

As can be seen below (StackWalker did not use the Symbols location, so I added a better trace at the end):
- the first few gdk_threads_enter/gdk_threads_leave traces are pretty much repeated a lot with the same thread pointer (main thread)
- when the window is moved (last gdk_threads_enter before the deadlock), a new lock is taken while the first is still held within the same main thread and thus the deadlock.

I am unsure of where the problem exactly is, or if Win32 should maybe just use a GRecMutex for the GDK lock for the time being with Glib 2.32?

Anyway, if I can give more information or help with testing/debugging let me know.


*********************** gdk_threads_enter: 032CB3C0 ***********************
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\stackwalker.cpp (920): StackWalker::ShowCallstack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\show_stack.cpp (8): show_stack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (692): gdk_threads_impl_lock
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (669): gdk_threads_enter
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3374): gdk_event_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (2541): g_main_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3075): g_main_context_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3146): g_main_context_iterate
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3340): g_main_loop_run
c:\opt\vs10-gtk2\gtk+-3.4.3\gtk\gtkmain.c (1161): gtk_main
c:\opt\vs10-gtk2\gtk+-3.4.3\build\win32\vs10\gtk-thread.c (155): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): mainCRTStartup
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74A2339A)
74A2339A (kernel32): (filename not available): BaseThreadInitThunk
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EF2)
77019EF2 (ntdll): (filename not available): RtlInitializeExceptionChain
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EC5)
77019EC5 (ntdll): (filename not available): RtlInitializeExceptionChain
*********************** gdk_threads_leave: 032CB3C0 ***********************
*********************** gdk_threads_enter: 032CB3C0 ***********************
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\stackwalker.cpp (920): StackWalker::ShowCallstack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\show_stack.cpp (8): show_stack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (692): gdk_threads_impl_lock
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (669): gdk_threads_enter
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3331): gdk_event_prepare
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (2836): g_main_context_prepare
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3126): g_main_context_iterate
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3340): g_main_loop_run
c:\opt\vs10-gtk2\gtk+-3.4.3\gtk\gtkmain.c (1161): gtk_main
c:\opt\vs10-gtk2\gtk+-3.4.3\build\win32\vs10\gtk-thread.c (155): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): mainCRTStartup
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74A2339A)
74A2339A (kernel32): (filename not available): BaseThreadInitThunk
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EF2)
77019EF2 (ntdll): (filename not available): RtlInitializeExceptionChain
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EC5)
77019EC5 (ntdll): (filename not available): RtlInitializeExceptionChain
*********************** gdk_threads_leave: 032CB3C0 ***********************
*********************** gdk_threads_enter: 032CB3C0 ***********************
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\stackwalker.cpp (920): StackWalker::ShowCallstack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\show_stack.cpp (8): show_stack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (692): gdk_threads_impl_lock
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (669): gdk_threads_enter
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3374): gdk_event_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (2541): g_main_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3075): g_main_context_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3146): g_main_context_iterate
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3340): g_main_loop_run
c:\opt\vs10-gtk2\gtk+-3.4.3\gtk\gtkmain.c (1161): gtk_main
c:\opt\vs10-gtk2\gtk+-3.4.3\build\win32\vs10\gtk-thread.c (155): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): mainCRTStartup
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74A2339A)
74A2339A (kernel32): (filename not available): BaseThreadInitThunk
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EF2)
77019EF2 (ntdll): (filename not available): RtlInitializeExceptionChain
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EC5)
77019EC5 (ntdll): (filename not available): RtlInitializeExceptionChain
*********************** gdk_threads_enter: 032CB3C0 ***********************
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\stackwalker.cpp (920): StackWalker::ShowCallstack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\show_stack.cpp (8): show_stack
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (692): gdk_threads_impl_lock
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\gdk.c (669): gdk_threads_enter
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3331): gdk_event_prepare
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (2836): g_main_context_prepare
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3126): g_main_context_iterate
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3172): g_main_context_pending
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (1604): modal_timer_proc
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (2820): gdk_event_translate
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (261): inner_window_procedure
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (292): _gdk_win32_window_procedure
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB62FA)
74BB62FA (USER32): (filename not available): gapfnScSendMessage
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB7316)
74BB7316 (USER32): (filename not available): GetDC
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6DE8)
74BB6DE8 (USER32): (filename not available): GetThreadDesktop
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB8FA7)
74BB8FA7 (USER32): (filename not available): LoadStringW
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 76FF010A)
76FF010A (ntdll): (filename not available): KiUserCallbackDispatcher
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6A8C)
74BB6A8C (USER32): (filename not available): gapfnScSendMessage
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71287744)
71287744 (uxtheme): (filename not available): GetThemeBool
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 7128A092)
7128A092 (uxtheme): (filename not available): SetWindowThemeAttribute
ERROR: SymGetSymFromAddr64, GetLastError: 487 (Address: 71280B0D)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71280B0D)
71280B0D (uxtheme): (filename not available): (function-name not available)
ERROR: SymGetSymFromAddr64, GetLastError: 487 (Address: 71280B96)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71280B96)
71280B96 (uxtheme): (filename not available): (function-name not available)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB729A)
74BB729A (USER32): (filename not available): GetPropW
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (275): inner_window_procedure
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (292): _gdk_win32_window_procedure
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB62FA)
74BB62FA (USER32): (filename not available): gapfnScSendMessage
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB7316)
74BB7316 (USER32): (filename not available): GetDC
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6DE8)
74BB6DE8 (USER32): (filename not available): GetThreadDesktop
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6E44)
74BB6E44 (USER32): (filename not available): GetThreadDesktop
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 76FF010A)
76FF010A (ntdll): (filename not available): KiUserCallbackDispatcher
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6A8C)
74BB6A8C (USER32): (filename not available): gapfnScSendMessage
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71287744)
71287744 (uxtheme): (filename not available): GetThemeBool
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71296E85)
71296E85 (uxtheme): (filename not available): GetCurrentThemeName
ERROR: SymGetSymFromAddr64, GetLastError: 487 (Address: 71280B0D)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71280B0D)
71280B0D (uxtheme): (filename not available): (function-name not available)
ERROR: SymGetSymFromAddr64, GetLastError: 487 (Address: 71280B96)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 71280B96)
71280B96 (uxtheme): (filename not available): (function-name not available)
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB729A)
74BB729A (USER32): (filename not available): GetPropW
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (275): inner_window_procedure
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (292): _gdk_win32_window_procedure
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB62FA)
74BB62FA (USER32): (filename not available): gapfnScSendMessage
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB6D3A)
74BB6D3A (USER32): (filename not available): GetThreadDesktop
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB77C4)
74BB77C4 (USER32): (filename not available): CharPrevW
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74BB788A)
74BB788A (USER32): (filename not available): DispatchMessageW
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3319): _gdk_win32_display_queue_events
c:\opt\vs10-gtk2\gtk+-3.4.3\gdk\win32\gdkevents-win32.c (3374): gdk_event_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (2541): g_main_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3075): g_main_context_dispatch
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3146): g_main_context_iterate
c:\opt\vs10-gtk2\glib-2.32.3\glib\gmain.c (3340): g_main_loop_run
c:\opt\vs10-gtk2\gtk+-3.4.3\gtk\gtkmain.c (1161): gtk_main
c:\opt\vs10-gtk2\gtk+-3.4.3\build\win32\vs10\gtk-thread.c (155): main
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): mainCRTStartup
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 74A2339A)
74A2339A (kernel32): (filename not available): BaseThreadInitThunk
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EF2)
77019EF2 (ntdll): (filename not available): RtlInitializeExceptionChain
ERROR: SymGetLineFromAddr64, GetLastError: 487 (Address: 77019EC5)
77019EC5 (ntdll): (filename not available): RtlInitializeExceptionChain
*********************** deadlock: 032CB3C0 ***********************


--------------------- VS2010 callstack -------------------
 	ntdll.dll!_ZwWaitForKeyedEvent@16()  + 0x15 bytes	
 	ntdll.dll!_ZwWaitForKeyedEvent@16()  + 0x15 bytes	
>	glib-2-vs10.dll!g_mutex_lock(_GMutex * mutex=0x0f644b00)  Line 139 + 0xc bytes	C
 	gdk-win32-3-vs10.dll!gdk_threads_impl_lock()  Line 687 + 0xa bytes	C
 	gdk-win32-3-vs10.dll!gdk_threads_enter()  Line 669 + 0x8 bytes	C
 	gdk-win32-3-vs10.dll!gdk_event_prepare(_GSource * source=0x030bd3c8, int * timeout=0x0018defc)  Line 3331	C
 	glib-2-vs10.dll!g_main_context_prepare(_GMainContext * context=0x030be5d8, int * priority=0x0018e05c)  Line 2836 + 0xd bytes	C
 	glib-2-vs10.dll!g_main_context_iterate(_GMainContext * context=0x030be5d8, int block=0, int dispatch=0, _GThread * self=0x030fa3c0)  Line 3126 + 0xd bytes	C
 	glib-2-vs10.dll!g_main_context_pending(_GMainContext * context=0x030be5d8)  Line 3172 + 0x13 bytes	C
 	gdk-win32-3-vs10.dll!modal_timer_proc(HWND__ * hwnd=0x00000000, unsigned int msg=0, unsigned int id=0, unsigned long time=0)  Line 1604 + 0x10 bytes	C
 	gdk-win32-3-vs10.dll!gdk_event_translate(tagMSG * msg=0x0018ea78, int * ret_valp=0x0018ea60)  Line 2820	C
 	gdk-win32-3-vs10.dll!inner_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=71, unsigned int wparam=0, long lparam=1633520)  Line 261 + 0xd bytes	C
 	gdk-win32-3-vs10.dll!_gdk_win32_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=71, unsigned int wparam=0, long lparam=1633520)  Line 292 + 0x15 bytes	C
 	user32.dll!_InternalCallWinProc@20()  + 0x23 bytes	
 	user32.dll!_UserCallWinProcCheckWow@32()  + 0x693 bytes	
 	user32.dll!_DispatchClientMessage@24()  + 0x51 bytes	
 	user32.dll!___fnINLPWINDOWPOS@4()  + 0x2c bytes	
 	ntdll.dll!_KiUserCallbackDispatcher@12()  + 0x2e bytes	
 	user32.dll!_NtUserMessageCall@28()  + 0x15 bytes	
 	user32.dll!_RealDefWindowProcWorker@24()  + 0xace bytes	
 	user32.dll!_RealDefWindowProcW@16()  + 0x2a bytes	
 	uxtheme.dll!DoMsgDefault()  + 0x29 bytes	
 	uxtheme.dll!OnDwpSysCommand()  + 0x29 bytes	
 	uxtheme.dll!_ThemeDefWindowProc()  + 0xfb bytes	
 	uxtheme.dll!_ThemeDefWindowProcW@16()  + 0x18 bytes	
 	user32.dll!_DefWindowProcW@16()  + 0x805 bytes	
 	gdk-win32-3-vs10.dll!inner_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=274, unsigned int wparam=61458, long lparam=7602404)  Line 275 + 0x18 bytes	C
 	gdk-win32-3-vs10.dll!_gdk_win32_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=274, unsigned int wparam=61458, long lparam=7602404)  Line 292 + 0x15 bytes	C
 	user32.dll!_InternalCallWinProc@20()  + 0x23 bytes	
 	user32.dll!_UserCallWinProcCheckWow@32()  + 0x693 bytes	
 	user32.dll!_DispatchClientMessage@24()  + 0x51 bytes	
 	user32.dll!___fnDWORD@4()  + 0x2b bytes	
 	ntdll.dll!_KiUserCallbackDispatcher@12()  + 0x2e bytes	
 	user32.dll!_NtUserMessageCall@28()  + 0x15 bytes	
 	user32.dll!_RealDefWindowProcWorker@24()  + 0xace bytes	
 	user32.dll!_RealDefWindowProcW@16()  + 0x2a bytes	
 	uxtheme.dll!DoMsgDefault()  + 0x29 bytes	
 	uxtheme.dll!OnDwpNcLButtonDown()  + 0x4b bytes	
 	uxtheme.dll!_ThemeDefWindowProc()  + 0xfb bytes	
 	uxtheme.dll!_ThemeDefWindowProcW@16()  + 0x18 bytes	
 	user32.dll!_DefWindowProcW@16()  + 0x805 bytes	
 	gdk-win32-3-vs10.dll!inner_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=161, unsigned int wparam=2, long lparam=7602404)  Line 275 + 0x18 bytes	C
 	gdk-win32-3-vs10.dll!_gdk_win32_window_procedure(HWND__ * hwnd=0x013f0622, unsigned int message=161, unsigned int wparam=2, long lparam=7602404)  Line 292 + 0x15 bytes	C
 	user32.dll!_InternalCallWinProc@20()  + 0x23 bytes	
 	user32.dll!_UserCallWinProcCheckWow@32()  + 0xb7 bytes	
 	user32.dll!_DispatchMessageWorker@8()  + 0xed bytes	
 	user32.dll!_DispatchMessageW@4()  + 0xf bytes	
 	gdk-win32-3-vs10.dll!_gdk_win32_display_queue_events(_GdkDisplay * display=0x030a4020)  Line 3319 + 0xc bytes	C
 	gdk-win32-3-vs10.dll!gdk_event_dispatch(_GSource * source=0x030bd3c8, int (void *)* callback=0x00000000, void * user_data=0x00000000)  Line 3374 + 0xb bytes	C
 	glib-2-vs10.dll!g_main_dispatch(_GMainContext * context=0x030be5d8)  Line 2541 + 0x11 bytes	C
 	glib-2-vs10.dll!g_main_context_dispatch(_GMainContext * context=0x030be5d8)  Line 3075 + 0x9 bytes	C
 	glib-2-vs10.dll!g_main_context_iterate(_GMainContext * context=0x030be5d8, int block=1, int dispatch=1, _GThread * self=0x030fa3c0)  Line 3146 + 0x9 bytes	C
 	glib-2-vs10.dll!g_main_loop_run(_GMainLoop * loop=0x03178bc0)  Line 3340 + 0x13 bytes	C
 	gtk-win32-3-vs10.dll!gtk_main()  Line 1161 + 0x9 bytes	C
 	gtk3-thread.exe!main(int argc=1, char * * argv=0x017a1cf0)  Line 150	C
 	gtk3-thread.exe!__tmainCRTStartup()  Line 555 + 0x19 bytes	C
 	gtk3-thread.exe!mainCRTStartup()  Line 371	C
 	kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes	
 	ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes	
 	ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes	



/*-------------------------------------------------------------------------
 * Filename:      gtk-thread.c
 * Version:       1.99.1
 * Copyright:     Copyright (C) 1999, Erik Mouw
 * Author:        Erik Mouw <J A K Mouw its tudelft nl>
 * Description:   GTK threads example.
 * Created at:    Sun Oct 17 21:27:09 1999
 * Modified by:   Owen Taylor <otaylor gtk org>
 * Modified at:   Wed May 28 10:43:00 2003
 *-----------------------------------------------------------------------*/
/*
 * Compile with:
 *
 * gcc -mms-bitfields -mthreads -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`
 *
 * Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions.
 *
 */

#include <windows.h>
//#include <unistd.h>
#include <gtk/gtk.h>

#define YES_IT_IS    (1)
#define NO_IT_IS_NOT (0)

typedef struct
{
  GtkWidget *label;
  int what;
} yes_or_no_args;

G_LOCK_DEFINE_STATIC (yes_or_no);
static volatile int yes_or_no = YES_IT_IS;

void destroy(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}

gint myfunc(void *args)
{
  yes_or_no_args *data = (yes_or_no_args *)args;

  /* get GTK thread lock */
  //gdk_threads_enter();

  G_LOCK(yes_or_no);

  /* set label text */
  if(data->what == YES_IT_IS)
    gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
  else
    gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");

  G_UNLOCK(yes_or_no);

  /* Make sure all X commands are sent to the X server; not strictly
   * necessary here, but always a good idea when you do anything
   * from a thread other than the one where the main loop is running.
   */
  gdk_flush ();

  /* release GTK thread lock */
  //gdk_threads_leave();

  return FALSE; // call only once
}

void *argument_thread(void *args)
{
  yes_or_no_args *data = (yes_or_no_args *)args;
  gboolean say_something;

  for(;;)
    {
      /* sleep a while */
      _sleep(g_random_int_range (1, 4));

      /* lock the yes_or_no_variable */
      G_LOCK(yes_or_no);

      /* do we have to say something? */
      say_something = (yes_or_no != data->what);

      if(say_something)
	{
	  /* set the variable */
	  yes_or_no = data->what;
	}

      /* Unlock the yes_or_no variable */
      G_UNLOCK(yes_or_no);

      if(say_something)
	{
	  //g_idle_add(myfunc, data);
	  gdk_threads_add_idle(myfunc, data);
	}
    }

  return NULL;
}

int main(int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *label;
  GError *error = NULL;
  yes_or_no_args yes_args, no_args;

  /* init threads */
  //g_thread_init(NULL);
  gdk_threads_init();

  /* init gtk */
  gtk_init(&argc, &argv);

  /* create a window */
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  g_signal_connect(window, "destroy",
		   G_CALLBACK(destroy), NULL);

  gtk_container_set_border_width(GTK_CONTAINER (window), 10);

  /* create a label */
  label = gtk_label_new("And now for something completely different ...");
  gtk_container_add(GTK_CONTAINER(window), label);

  /* show everything */
  gtk_widget_show(label);
  gtk_widget_show (window);

  /* create the threads */
  yes_args.label = label;
  yes_args.what = YES_IT_IS;
  if (!g_thread_create(argument_thread, &yes_args, FALSE, &error))
    {
      g_printerr ("Failed to create YES thread: %s\n", error->message);
      return 1;
    }

  no_args.label = label;
  no_args.what = NO_IT_IS_NOT;
  if (!g_thread_create(argument_thread, &no_args, FALSE, &error))
    {
      g_printerr ("Failed to create NO thread: %s\n", error->message);
      return 1;
    }

  /* enter the GTK main loop */
  gdk_threads_enter();
  gtk_main();
  gdk_threads_leave();

  return 0;
}


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