diff options
author | Joe Mistachkin <joe@mistachkin.com> | 2013-10-28 19:34:15 (GMT) |
---|---|---|
committer | Joe Mistachkin <joe@mistachkin.com> | 2013-10-28 19:34:15 (GMT) |
commit | a768abbd8e38f9b00f174006ccd0050e3f0881c3 (patch) | |
tree | 915ca3efb40e0225aea8187ee4c485597bddf7c7 | |
parent | 9948d29038eeaaed7e7f3a5d39b22b5462f2c825 (diff) | |
download | tcl-a768abbd8e38f9b00f174006ccd0050e3f0881c3.zip tcl-a768abbd8e38f9b00f174006ccd0050e3f0881c3.tar.gz tcl-a768abbd8e38f9b00f174006ccd0050e3f0881c3.tar.bz2 |
Prototype of fix for ticket [414d10346b].
-rw-r--r-- | unix/tclUnixNotfy.c | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index f41ef68..025dfd4 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -128,15 +128,6 @@ static Tcl_ThreadDataKey dataKey; static int notifierCount = 0; /* - * The following static stores the process ID of the initialized notifier - * thread. If it changes, we have passed a fork and we should start a new - * notifier thread. - * - * You must hold the notifierMutex lock before accessing this variable. - */ -static pid_t processIDInitialized = 0; - -/* * The following variable points to the head of a doubly-linked list of * ThreadSpecificData structures for all threads that are currently waiting on * an event. @@ -204,9 +195,9 @@ static Tcl_ThreadId notifierThread; static void NotifierThreadProc(ClientData clientData); #if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) static int atForkInit = 0; -static void AtForkPrepare(void); -static void AtForkParent(void); -static void AtForkChild(void); +static void AtForkPrepareProc(void); +static void AtForkParentProc(void); +static void AtForkChildProc(void); #endif /* HAVE_PTHREAD_ATFORK */ #endif /* TCL_THREADS */ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); @@ -282,14 +273,16 @@ Tcl_InitNotifier(void) */ Tcl_MutexLock(¬ifierMutex); + #if defined(HAVE_PTHREAD_ATFORK) && !defined(__APPLE__) /* - * Install pthread_atfork handlers to reinitialize the notifier in the - * child of a fork. + * Install pthread_atfork() handlers to deal with the notifier in the + * forked child. */ if (!atForkInit) { - int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild); + int result = pthread_atfork(AtForkPrepareProc, AtForkParentProc, + AtForkChildProc); if (result) { Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed"); @@ -297,23 +290,12 @@ Tcl_InitNotifier(void) atForkInit = 1; } #endif /* HAVE_PTHREAD_ATFORK */ - /* - * Check if my process id changed, e.g. I was forked - * In this case, restart the notifier thread and close the - * pipe to the original notifier thread - */ - if (notifierCount > 0 && processIDInitialized != getpid()) { - notifierCount = 0; - processIDInitialized = 0; - close(triggerPipe); - triggerPipe = -1; - } + if (notifierCount == 0) { if (TclpThreadCreate(¬ifierThread, NotifierThreadProc, NULL, TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) { Tcl_Panic("Tcl_InitNotifier: unable to start notifier thread"); } - processIDInitialized = getpid(); } notifierCount++; @@ -1277,7 +1259,7 @@ NotifierThreadProc( /* *---------------------------------------------------------------------- * - * AtForkPrepare -- + * AtForkPrepareProc -- * * Lock the notifier in preparation for a fork. * @@ -1291,14 +1273,15 @@ NotifierThreadProc( */ static void -AtForkPrepare(void) +AtForkPrepareProc(void) { + Tcl_MutexLock(¬ifierMutex); } /* *---------------------------------------------------------------------- * - * AtForkParent -- + * AtForkParentProc -- * * Unlock the notifier in the parent after a fork. * @@ -1312,16 +1295,18 @@ AtForkPrepare(void) */ static void -AtForkParent(void) +AtForkParentProc(void) { + Tcl_MutexUnlock(¬ifierMutex); } /* *---------------------------------------------------------------------- * - * AtForkChild -- + * AtForkChildProc -- * - * Unlock and reinstall the notifier in the child after a fork. + * Assumes the notifier mutex is already held. Reset the notifier + * state and then re-initializes it for the child process. * * Results: * None. @@ -1333,11 +1318,52 @@ AtForkParent(void) */ static void -AtForkChild(void) +AtForkChildProc(void) { - notifierMutex = NULL; - notifierCV = NULL; + /* + * Close the trigger pipe and reset it to the default value. This + * should cause it to be re-opened when the notifier is subsequently + * initialized. Since the trigger pipe is opened via the notifier + * thread (which may never have started?), check it before attempting + * to close it. + */ + + if (triggerPipe >= 0) { + close(triggerPipe); + triggerPipe = -1; + } + + /* + * Since the notifier thread is not really running, zero out its ID. + * This step is not strictly necessary since its value will not be + * checked before it is re-created. + */ + + notifierThread = (Tcl_ThreadId) 0; + + /* + * Reset the notifier reference count to zero (i.e. not initialized). + * This should force the notifier initialization code to be re-run the + * very next time Tcl_InitNotifier is called, which will be just below + * this statement. + */ + + notifierCount = 0; + + /* + * Force the notifier subsystem to be initialized now. This should + * create the notifier thread in this process. Subsequently, that new + * thread will re-open the trigger pipe. + */ + Tcl_InitNotifier(); + + /* + * Finally, release the notifier mutex (which has been held since the + * AtForkPrepareProc() was called via pthread_atfork()). + */ + + Tcl_MutexUnlock(¬ifierMutex); } #endif /* HAVE_PTHREAD_ATFORK */ |