diff options
author | das <das> | 2006-05-27 05:23:03 (GMT) |
---|---|---|
committer | das <das> | 2006-05-27 05:23:03 (GMT) |
commit | d9fb2d616e85d1da1ad401a0c964dc9c56e85ee8 (patch) | |
tree | 9a10a778217f42b4a31a622641a6fc51a5ea8ff9 /macosx | |
parent | f95f9d46f4c8c2317e762fb2c94e291759e5c97c (diff) | |
download | tcl-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.c | 115 |
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 */ |