Glib 2.32.x, Win32 and threading
- From: "Martin Schlemmer" <Martin Schlemmer nwu ac za>
- To: <gtk-list gnome org>
- Subject: Glib 2.32.x, Win32 and threading
- Date: Tue, 03 Jul 2012 20:59:11 +0200
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]