|
|
2e5d8e |
diff --git a/unix/configure.in b/unix/configure.in
|
|
|
2e5d8e |
index b606b74..46dec02 100755
|
|
|
2e5d8e |
--- a/unix/configure.in
|
|
|
2e5d8e |
+++ b/unix/configure.in
|
|
|
2e5d8e |
@@ -491,6 +491,12 @@ SC_ENABLE_LANGINFO
|
|
|
2e5d8e |
AC_CHECK_FUNCS(chflags)
|
|
|
2e5d8e |
|
|
|
2e5d8e |
#--------------------------------------------------------------------
|
|
|
2e5d8e |
+# Check for support of pthread_atfork function
|
|
|
2e5d8e |
+#--------------------------------------------------------------------
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+AC_CHECK_FUNCS(pthread_atfork)
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+#--------------------------------------------------------------------
|
|
|
2e5d8e |
# Check for support of isnan() function or macro
|
|
|
2e5d8e |
#--------------------------------------------------------------------
|
|
|
2e5d8e |
|
|
|
2e5d8e |
@@ -513,7 +519,6 @@ if test "`uname -s`" = "Darwin" ; then
|
|
|
2e5d8e |
if test $tcl_corefoundation = yes; then
|
|
|
2e5d8e |
AC_CHECK_HEADERS(libkern/OSAtomic.h)
|
|
|
2e5d8e |
AC_CHECK_FUNCS(OSSpinLockLock)
|
|
|
2e5d8e |
- AC_CHECK_FUNCS(pthread_atfork)
|
|
|
2e5d8e |
fi
|
|
|
2e5d8e |
AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?])
|
|
|
2e5d8e |
AC_DEFINE(TCL_DEFAULT_ENCODING, "utf-8",
|
|
|
2e5d8e |
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
|
|
|
2e5d8e |
index 51f0b1f..9006906 100644
|
|
|
2e5d8e |
--- a/unix/tclUnixNotfy.c
|
|
|
2e5d8e |
+++ b/unix/tclUnixNotfy.c
|
|
|
2e5d8e |
@@ -128,6 +128,15 @@ static Tcl_ThreadDataKey dataKey;
|
|
|
2e5d8e |
static int notifierCount = 0;
|
|
|
2e5d8e |
|
|
|
2e5d8e |
/*
|
|
|
2e5d8e |
+ * The following static stores the process ID of the initialized notifier
|
|
|
2e5d8e |
+ * thread. If it changes, we have passed a fork and we should start a new
|
|
|
2e5d8e |
+ * notifier thread.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * You must hold the notifierMutex lock before accessing this variable.
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+static pid_t processIDInitialized = 0;
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+/*
|
|
|
2e5d8e |
* The following variable points to the head of a doubly-linked list of
|
|
|
2e5d8e |
* ThreadSpecificData structures for all threads that are currently waiting on
|
|
|
2e5d8e |
* an event.
|
|
|
2e5d8e |
@@ -193,7 +202,13 @@ static Tcl_ThreadId notifierThread;
|
|
|
2e5d8e |
|
|
|
2e5d8e |
#ifdef TCL_THREADS
|
|
|
2e5d8e |
static void NotifierThreadProc(ClientData clientData);
|
|
|
2e5d8e |
-#endif
|
|
|
2e5d8e |
+#ifdef HAVE_PTHREAD_ATFORK
|
|
|
2e5d8e |
+static int atForkInit = 0;
|
|
|
2e5d8e |
+static void AtForkPrepare(void);
|
|
|
2e5d8e |
+static void AtForkParent(void);
|
|
|
2e5d8e |
+static void AtForkChild(void);
|
|
|
2e5d8e |
+#endif /* HAVE_PTHREAD_ATFORK */
|
|
|
2e5d8e |
+#endif /* TCL_THREADS */
|
|
|
2e5d8e |
static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
|
|
|
2e5d8e |
|
|
|
2e5d8e |
/*
|
|
|
2e5d8e |
@@ -267,11 +282,38 @@ Tcl_InitNotifier(void)
|
|
|
2e5d8e |
*/
|
|
|
2e5d8e |
|
|
|
2e5d8e |
Tcl_MutexLock(¬ifierMutex);
|
|
|
2e5d8e |
+#ifdef HAVE_PTHREAD_ATFORK
|
|
|
2e5d8e |
+ /*
|
|
|
2e5d8e |
+ * Install pthread_atfork handlers to reinitialize the notifier in the
|
|
|
2e5d8e |
+ * child of a fork.
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+ if (!atForkInit) {
|
|
|
2e5d8e |
+ int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+ if (result) {
|
|
|
2e5d8e |
+ Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
|
|
|
2e5d8e |
+ }
|
|
|
2e5d8e |
+ atForkInit = 1;
|
|
|
2e5d8e |
+ }
|
|
|
2e5d8e |
+#endif
|
|
|
2e5d8e |
+ /*
|
|
|
2e5d8e |
+ * Check if my process id changed, e.g. I was forked
|
|
|
2e5d8e |
+ * In this case, restart the notifier thread and close the
|
|
|
2e5d8e |
+ * pipe to the original notifier thread
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+ if (notifierCount > 0 && processIDInitialized != getpid()) {
|
|
|
2e5d8e |
+ notifierCount = 0;
|
|
|
2e5d8e |
+ processIDInitialized = 0;
|
|
|
2e5d8e |
+ close(triggerPipe);
|
|
|
2e5d8e |
+ triggerPipe = -1;
|
|
|
2e5d8e |
+ }
|
|
|
2e5d8e |
if (notifierCount == 0) {
|
|
|
2e5d8e |
if (TclpThreadCreate(¬ifierThread, NotifierThreadProc, NULL,
|
|
|
2e5d8e |
TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
|
|
|
2e5d8e |
Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread");
|
|
|
2e5d8e |
}
|
|
|
2e5d8e |
+ processIDInitialized = getpid();
|
|
|
2e5d8e |
}
|
|
|
2e5d8e |
notifierCount++;
|
|
|
2e5d8e |
|
|
|
2e5d8e |
@@ -1230,6 +1272,73 @@ NotifierThreadProc(
|
|
|
2e5d8e |
|
|
|
2e5d8e |
TclpThreadExit (0);
|
|
|
2e5d8e |
}
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+#ifdef HAVE_PTHREAD_ATFORK
|
|
|
2e5d8e |
+/*
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * AtForkPrepare --
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Lock the notifier in preparation for a fork.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Results:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Side effects:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+static void
|
|
|
2e5d8e |
+AtForkPrepare(void)
|
|
|
2e5d8e |
+{
|
|
|
2e5d8e |
+}
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+/*
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * AtForkParent --
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Unlock the notifier in the parent after a fork.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Results:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Side effects:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+static void
|
|
|
2e5d8e |
+AtForkParent(void)
|
|
|
2e5d8e |
+{
|
|
|
2e5d8e |
+}
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+/*
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * AtForkChild --
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Unlock and reinstall the notifier in the child after a fork.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Results:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ * Side effects:
|
|
|
2e5d8e |
+ * None.
|
|
|
2e5d8e |
+ *
|
|
|
2e5d8e |
+ *----------------------------------------------------------------------
|
|
|
2e5d8e |
+ */
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
+static void
|
|
|
2e5d8e |
+AtForkChild(void)
|
|
|
2e5d8e |
+{
|
|
|
2e5d8e |
+ Tcl_InitNotifier();
|
|
|
2e5d8e |
+}
|
|
|
2e5d8e |
+#endif /* HAVE_PTHREAD_ATFORK */
|
|
|
2e5d8e |
+
|
|
|
2e5d8e |
#endif /* TCL_THREADS */
|
|
|
2e5d8e |
|
|
|
2e5d8e |
#endif /* HAVE_COREFOUNDATION */
|