diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 093d990af33dad8353e98d35988902daf858c3cd..d218108029538f50937a95b19120372b990b7f34 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -2,7 +2,7 @@
  * pltcl.c		- PostgreSQL support for Tcl as
  *				  procedural language (PL)
  *
- *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.112 2007/04/02 03:49:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.113 2007/09/21 00:30:49 tgl Exp $
  *
  **********************************************************************/
 
@@ -33,9 +33,11 @@
 #include "utils/syscache.h"
 #include "utils/typcache.h"
 
+#define HAVE_TCL_VERSION(maj,min) \
+	((TCL_MAJOR_VERSION > maj) || \
+	 (TCL_MAJOR_VERSION == maj && TCL_MINOR_VERSION >= min))
 
-#if defined(UNICODE_CONVERSION) && TCL_MAJOR_VERSION == 8 \
-	&& TCL_MINOR_VERSION > 0
+#if defined(UNICODE_CONVERSION) && HAVE_TCL_VERSION(8,1)
 
 #include "mb/pg_wchar.h"
 
@@ -164,6 +166,68 @@ static void pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc,
 						   Tcl_DString *retval);
 
 
+/*
+ * Hack to override Tcl's builtin Notifier subsystem.  This prevents the
+ * backend from becoming multithreaded, which breaks all sorts of things.
+ * That happens in the default version of Tcl_InitNotifier if the TCL library
+ * has been compiled with multithreading support (i.e. when TCL_THREADS is
+ * defined under Unix, and in all cases under Windows).
+ * It's okay to disable the notifier because we never enter the Tcl event loop
+ * from Postgres, so the notifier capabilities are initialized, but never
+ * used.  Only InitNotifier and DeleteFileHandler ever seem to get called
+ * within Postgres, but we implement all the functions for completeness.
+ * We can only fix this with Tcl >= 8.2, when Tcl_SetNotifier() appeared.
+ */
+#if HAVE_TCL_VERSION(8,2)
+
+static ClientData
+pltcl_InitNotifier(void)
+{
+	static int fakeThreadKey;	/* To give valid address for ClientData */
+
+	return (ClientData) &(fakeThreadKey);
+}
+
+static void
+pltcl_FinalizeNotifier(ClientData clientData)
+{
+}
+
+static void
+pltcl_SetTimer(Tcl_Time *timePtr)
+{
+}
+
+static void
+pltcl_AlertNotifier(ClientData clientData)
+{
+}
+
+static void
+pltcl_CreateFileHandler(int fd, int mask,
+						Tcl_FileProc *proc, ClientData clientData)
+{
+}
+
+static void
+pltcl_DeleteFileHandler(int fd)
+{
+}
+
+static void
+pltcl_ServiceModeHook(int mode)
+{
+}
+
+static int
+pltcl_WaitForEvent(Tcl_Time *timePtr)
+{
+	return 0;
+}
+
+#endif /* HAVE_TCL_VERSION(8,2) */
+
+
 /*
  * This routine is a crock, and so is everyplace that calls it.  The problem
  * is that the cached form of pltcl functions/queries is allocated permanently
@@ -198,6 +262,25 @@ _PG_init(void)
 	Tcl_FindExecutable("");
 #endif
 
+#if HAVE_TCL_VERSION(8,2)
+	/*
+	 * Override the functions in the Notifier subsystem.  See comments above.
+	 */
+	{
+		Tcl_NotifierProcs notifier;
+
+		notifier.setTimerProc          = pltcl_SetTimer;
+		notifier.waitForEventProc      = pltcl_WaitForEvent;
+		notifier.createFileHandlerProc = pltcl_CreateFileHandler;
+		notifier.deleteFileHandlerProc = pltcl_DeleteFileHandler;
+		notifier.initNotifierProc      = pltcl_InitNotifier;
+		notifier.finalizeNotifierProc  = pltcl_FinalizeNotifier;
+		notifier.alertNotifierProc     = pltcl_AlertNotifier;
+		notifier.serviceModeHookProc   = pltcl_ServiceModeHook;
+		Tcl_SetNotifier(&notifier);
+	}
+#endif
+
 	/************************************************************
 	 * Create the dummy hold interpreter to prevent close of
 	 * stdout and stderr on DeleteInterp
@@ -1808,9 +1891,9 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 	PG_TRY();
 	{
 		/************************************************************
-		 * Resolve argument type names and then look them up by oid 
-         * in the system cache, and remember the required information 
-         * for input conversion.
+		 * Resolve argument type names and then look them up by oid
+		 * in the system cache, and remember the required information
+		 * for input conversion.
 		 ************************************************************/
 		for (i = 0; i < nargs; i++)
 		{