summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authordas <das>2006-05-27 05:23:03 (GMT)
committerdas <das>2006-05-27 05:23:03 (GMT)
commitd9fb2d616e85d1da1ad401a0c964dc9c56e85ee8 (patch)
tree9a10a778217f42b4a31a622641a6fc51a5ea8ff9 /macosx
parentf95f9d46f4c8c2317e762fb2c94e291759e5c97c (diff)
downloadtcl-d9fb2d616e85d1da1ad401a0c964dc9c56e85ee8.zip
tcl-d9fb2d616e85d1da1ad401a0c964dc9c56e85ee8.tar.gz
tcl-d9fb2d616e85d1da1ad401a0c964dc9c56e85ee8.tar.bz2
* macosx/tclMacOSXNotify.c: implemented pthread_atfork() handler that
* unix/tcl.m4 (Darwin): recreates CoreFoundation state and notifier thread in the child after a fork(). Note that pthread_atfork() is available starting with Tiger only. Because vfork() is used by the core on Darwin, [exec]/[open] are not affected by this fix, only extensions or embedders that call fork() directly (such as TclX). However, this only makes fork() safe from corefoundation tcl with --disable-threads; as on all platforms, forked children may deadlock in threaded tcl due to the potential for stale locked mutexes in the child. [Patch 923072] * unix/configure: autoconf-2.59
Diffstat (limited to 'macosx')
-rw-r--r--macosx/tclMacOSXNotify.c115
1 files changed, 112 insertions, 3 deletions
diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c
index cd09ccf..bdda1ce 100644
--- a/macosx/tclMacOSXNotify.c
+++ b/macosx/tclMacOSXNotify.c
@@ -8,12 +8,12 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001, Apple Computer, Inc.
* Copyright (c) 2005 Tcl Core Team.
- * Copyright (c) 2005 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2005-2006 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.1.2.5 2005/11/27 02:34:41 das Exp $
+ * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.1.2.6 2006/05/27 05:23:04 das Exp $
*/
#include "tclInt.h"
@@ -217,6 +217,13 @@ static pthread_t notifierThread;
static void NotifierThreadProc(ClientData clientData);
static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+
+#ifdef HAVE_PTHREAD_ATFORK
+static int atForkInit = 0;
+static void AtForkPrepare(void);
+static void AtForkParent(void);
+static void AtForkChild(void);
+#endif
/*
*----------------------------------------------------------------------
@@ -226,7 +233,7 @@ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
* Initializes the platform specific notifier state.
*
* Results:
- * Returns a handle to the notifier state for this thread..
+ * Returns a handle to the notifier state for this thread.
*
* Side effects:
* None.
@@ -266,6 +273,20 @@ Tcl_InitNotifier(void)
*/
LOCK_NOTIFIER_INIT;
+#ifdef HAVE_PTHREAD_ATFORK
+ /*
+ * Install pthread_atfork handlers to reinstall the notifier thread in the
+ * child of a fork.
+ */
+
+ if (!atForkInit) {
+ int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);
+ if (result) {
+ Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
+ }
+ atForkInit = 1;
+ }
+#endif
if (notifierCount == 0) {
int fds[2], status, result;
pthread_attr_t attr;
@@ -1038,4 +1059,92 @@ NotifierThreadProc(clientData)
}
pthread_exit (0);
}
+
+#ifdef HAVE_PTHREAD_ATFORK
+/*
+ *----------------------------------------------------------------------
+ *
+ * AtForkPrepare --
+ *
+ * Lock the notifier in preparation for a fork.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AtForkPrepare(void)
+{
+ LOCK_NOTIFIER_INIT;
+ LOCK_NOTIFIER;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AtForkParent --
+ *
+ * Unlock the notifier in the parent after a fork.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AtForkParent(void)
+{
+ UNLOCK_NOTIFIER;
+ UNLOCK_NOTIFIER_INIT;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AtForkChild --
+ *
+ * Unlock and reinstall the notifier in the child after a fork.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AtForkChild(void)
+{
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+
+ UNLOCK_NOTIFIER;
+ UNLOCK_NOTIFIER_INIT;
+ if (tsdPtr->runLoop) {
+ tsdPtr->runLoop = NULL;
+ CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
+ CFRelease(tsdPtr->runLoopSource);
+ tsdPtr->runLoopSource = NULL;
+ }
+ if (notifierCount > 0) {
+ notifierCount = 0;
+ /* Note that Tcl_FinalizeNotifier does not use its clientData
+ * parameter, so discard return value of Tcl_InitNotifier here and
+ * leave stale clientData in tclNotify.c's ThreadSpecificData.
+ */
+ Tcl_InitNotifier();
+ }
+}
+#endif /* HAVE_PTHREAD_ATFORK */
+
#endif /* HAVE_COREFOUNDATION */