*** pltcl.c.orig 2007-09-10 12:58:34.000000000 -0400 --- pltcl.c 2007-09-11 11:37:33.363222114 -0400 *************** *** 163,168 **** --- 163,258 ---- static void pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc, Tcl_DString *retval); + /********************************************************************** + * Declarations for functions overriden using Tcl_SetNotifier. + **********************************************************************/ + static int fakeThreadKey; /* To give valid address for ClientData */ + + static ClientData + pltcl_InitNotifier _ANSI_ARGS_((void)); + + static void + pltcl_FinalizeNotifier _ANSI_ARGS_((ClientData clientData)); + + static void + pltcl_SetTimer _ANSI_ARGS_((Tcl_Time *timePtr)); + + static void + pltcl_AlertNotifier _ANSI_ARGS_((ClientData clientData)); + + static void + pltcl_CreateFileHandler _ANSI_ARGS_((int fd, int mask, Tcl_FileProc *proc, ClientData clientData)); + + static void + pltcl_DeleteFileHandler _ANSI_ARGS_((int fd)); + + static void + pltcl_ServiceModeHook _ANSI_ARGS_((int mode)); + + static int + pltcl_WaitForEvent _ANSI_ARGS_((Tcl_Time *timePtr)); + + /********************************************************************** + * Definitions for functions overriden using Tcl_SetNotifier. + * These implementations effectively disable the TCL Notifier subsystem. + * This is okay because we never enter the TCL event loop from postgres, + * so the notifier capabilities are initialized, but never used. + * + * NOTE: Only InitNotifier and DeleteFileHandler ever seem to get called + * by postgres, but we implement all the functions for completeness. + **********************************************************************/ + + ClientData + pltcl_InitNotifier() + { + return (ClientData) &(fakeThreadKey); + } + + void + pltcl_FinalizeNotifier(clientData) + ClientData clientData; /* Not used. */ + { + } + + void + pltcl_SetTimer(timePtr) + Tcl_Time *timePtr; + { + } + + void + pltcl_AlertNotifier(clientData) + ClientData clientData; + { + } + + void + pltcl_CreateFileHandler(fd, mask, proc, clientData) + int fd; + int mask; + Tcl_FileProc *proc; + ClientData clientData; + { + } + + void + pltcl_DeleteFileHandler(fd) + int fd; + { + } + + void + pltcl_ServiceModeHook(mode) + int mode; + { + } + + int + pltcl_WaitForEvent(timePtr) + Tcl_Time *timePtr; /* Maximum block time, or NULL. */ + { + return 0; + } /* * This routine is a crock, and so is everyplace that calls it. The problem *************** *** 189,194 **** --- 279,287 ---- void _PG_init(void) { + /* Notifier structure used to override functions in Notifier subsystem*/ + Tcl_NotifierProcs notifier; + /* Be sure we do initialization only once (should be redundant now) */ if (pltcl_pm_init_done) return; *************** *** 199,204 **** --- 292,316 ---- #endif /************************************************************ + * Override the functions in the Notifier subsystem. + * + * We do this to prevent the postgres backend from becoming + * multithreaded, which 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). + ************************************************************/ + 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(¬ifier); + + /************************************************************ * Create the dummy hold interpreter to prevent close of * stdout and stderr on DeleteInterp ************************************************************/