diff plugins/tcl/tcl.c @ 13455:70197e8ac15c

[gaim-migrate @ 15830] This makes tcl.c a little uglier, but offers some significant benefits on win32. Firstly, we no longer call LoadLibrary() from within a DllMain function (which is fundamentally unsafe). Secondly, this prints a debugging message indicating that if gaim fails to load it is cygwin's fault. Thirdly, we now try to detect the loading of a cygwin tcl runtime and aborts loading the tcl plugin. The subsequent "hanging" is one of the most reported bugs, so this will hopefully reduce these bug reports. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 08 Mar 2006 03:41:58 +0000
parents 068282089843
children a84523152a24
line wrap: on
line diff
--- a/plugins/tcl/tcl.c	Tue Mar 07 20:11:35 2006 +0000
+++ b/plugins/tcl/tcl.c	Wed Mar 08 03:41:58 2006 +0000
@@ -325,8 +325,8 @@
 
 static gboolean tcl_load(GaimPlugin *plugin)
 {
-        if(!tcl_loaded)
-                return FALSE;
+	if(!tcl_loaded)
+		return FALSE;
 	tcl_glib_init();
 	tcl_signal_init();
 	tcl_plugins = g_hash_table_new(g_direct_hash, g_direct_equal);
@@ -382,45 +382,86 @@
 };
 
 #ifdef _WIN32
-extern Tcl_Interp* (CALLBACK* wtcl_CreateInterp)();
-extern void (CALLBACK* wtk_Init)(Tcl_Interp*);
+typedef Tcl_Interp* (CALLBACK* LPFNTCLCREATEINTERP)(void);
+typedef void        (CALLBACK* LPFNTKINIT)(Tcl_Interp*);
+
+LPFNTCLCREATEINTERP wtcl_CreateInterp = NULL;
+LPFNTKINIT wtk_Init = NULL;
 #undef Tcl_CreateInterp
 #define Tcl_CreateInterp wtcl_CreateInterp
 #undef Tk_Init
 #define Tk_Init wtk_Init
+
+static gboolean tcl_win32_init() {
+	gaim_debug(GAIM_DEBUG_INFO, "tcl",
+		"Initializing the Tcl runtime.  If Gaim doesn't load, it is "
+		"most likely because you have cygwin in your PATH and you "
+		"should remove it. See http://gaim.sf.net/win32 for more "
+		"information\n");
+
+	if(!(wtcl_CreateInterp = (LPFNTCLCREATEINTERP) wgaim_find_and_loadproc("tcl84.dll", "Tcl_CreateInterp"))) {
+		gaim_debug(GAIM_DEBUG_INFO, "tcl", "tcl_win32_init error loading Tcl_CreateInterp\n");
+		return FALSE;
+	}
+
+	if(!(wtk_Init = (LPFNTKINIT) wgaim_find_and_loadproc("tk84.dll", "Tk_Init"))) {
+		HMODULE mod;
+		gaim_debug(GAIM_DEBUG_INFO, "tcl", "tcl_win32_init error loading Tk_Init\n");
+		if((mod = GetModuleHandle("tcl84.dll")))
+			FreeLibrary(mod);
+		return FALSE;
+	}
+
+	if (GetModuleHandle("cygwin1.dll")) {
+		HMODULE mod;
+		gaim_debug(GAIM_DEBUG_INFO, "tcl", "Cygwin has been loaded by tcl84.dll and/or tk84.dll. Disabling Tcl support to avoid problems.\n");
+		if((mod = GetModuleHandle("tcl84.dll")))
+			FreeLibrary(mod);
+		if((mod = GetModuleHandle("tk84.dll")))
+			FreeLibrary(mod);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 #endif /* _WIN32 */
 
 static void tcl_init_plugin(GaimPlugin *plugin)
 {
 #ifdef USE_TCL_STUBS
-        Tcl_Interp *interp=NULL;
+	Tcl_Interp *interp = NULL;
 #endif
 	_tcl_plugin = plugin;
 
 #ifdef USE_TCL_STUBS
-        if(!(interp=Tcl_CreateInterp()))
-                return;
+#ifdef _WIN32
+	if(!tcl_win32_init())
+		return;
+#endif
+	if(!(interp = Tcl_CreateInterp()))
+		return;
 
-        if(!Tcl_InitStubs(interp, TCL_VERSION, 0)) {
-                gaim_debug(GAIM_DEBUG_ERROR, "tcl", "Tcl_InitStubs: %s\n", interp->result);
-                return;
-        }
+	if(!Tcl_InitStubs(interp, TCL_VERSION, 0)) {
+		gaim_debug(GAIM_DEBUG_ERROR, "tcl", "Tcl_InitStubs: %s\n", interp->result);
+		return;
+	}
 #endif
 
 	Tcl_FindExecutable("gaim");
 
 #if defined(USE_TK_STUBS) && defined(HAVE_TK)
-        Tk_Init(interp);
+	Tk_Init(interp);
 
-        if(!Tk_InitStubs(interp, TK_VERSION, 0)) {
-                gaim_debug(GAIM_DEBUG_ERROR, "tcl", "Error Tk_InitStubs: %s\n", interp->result);
-                Tcl_DeleteInterp(interp);
-                return;
-        }
+	if(!Tk_InitStubs(interp, TK_VERSION, 0)) {
+		gaim_debug(GAIM_DEBUG_ERROR, "tcl", "Error Tk_InitStubs: %s\n", interp->result);
+		Tcl_DeleteInterp(interp);
+		return;
+	}
 #endif
-        tcl_loaded = TRUE;
+	tcl_loaded = TRUE;
 #ifdef USE_TCL_STUBS
-        Tcl_DeleteInterp(interp);
+	Tcl_DeleteInterp(interp);
 #endif
 	tcl_loader_info.exts = g_list_append(tcl_loader_info.exts, "tcl");
 }