summaryrefslogtreecommitdiffstats
path: root/macosx/tclMacOSXNotify.c
diff options
context:
space:
mode:
authordas <das>2006-08-21 01:08:03 (GMT)
committerdas <das>2006-08-21 01:08:03 (GMT)
commitd70383944a28777ea679b1e1b4be38c2a42b3960 (patch)
tree1444f5611d45b011b9c6802f90b77083be59435f /macosx/tclMacOSXNotify.c
parentc8aa816f783a31a2a7a3315813d563c83a73a5d1 (diff)
downloadtcl-d70383944a28777ea679b1e1b4be38c2a42b3960.zip
tcl-d70383944a28777ea679b1e1b4be38c2a42b3960.tar.gz
tcl-d70383944a28777ea679b1e1b4be38c2a42b3960.tar.bz2
* macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is
already running (e.g. if Tcl_WaitForEvent was called recursively), re-run it in a custom run loop mode containing only the source for the notifier thread, otherwise wakeups from other sources added to the common run loop modes might get lost. * unix/tclUnixNotfy.c (Tcl_WaitForEvent): on 64-bit Darwin, pthread_cond_timedwait() appears to have a bug that causes it to wait forever when passed an absolute time which has already been exceeded by the system time; as a workaround, when given a very brief timeout, just do a poll on that platform. [Bug 1457797]
Diffstat (limited to 'macosx/tclMacOSXNotify.c')
-rw-r--r--macosx/tclMacOSXNotify.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/macosx/tclMacOSXNotify.c b/macosx/tclMacOSXNotify.c
index 6dfb379..73b1c92 100644
--- a/macosx/tclMacOSXNotify.c
+++ b/macosx/tclMacOSXNotify.c
@@ -13,7 +13,7 @@
* 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.9 2006/08/10 12:15:32 dkf Exp $
+ * RCS: @(#) $Id: tclMacOSXNotify.c,v 1.10 2006/08/21 01:08:03 das Exp $
*/
#include "tclInt.h"
@@ -237,6 +237,14 @@ static OSSpinLock notifierLock = 0;
static pthread_t notifierThread;
/*
+ * Custom run loop mode containing only the run loop source for the
+ * notifier thread.
+ */
+
+static const CFStringRef tclEventsOnlyRunLoopMode =
+ CFSTR("com.tcltk.tclEventsOnlyRunLoopMode");
+
+/*
* Static routines defined in this file.
*/
@@ -304,6 +312,7 @@ Tcl_InitNotifier(void)
Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource");
}
CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode);
tsdPtr->runLoopSource = runLoopSource;
tsdPtr->runLoop = runLoop;
}
@@ -897,14 +906,27 @@ Tcl_WaitForEvent(
if (!tsdPtr->eventReady) {
CFTimeInterval waitTime;
+ CFStringRef runLoopMode;
if (myTimePtr == NULL) {
waitTime = 1.0e10; /* Wait forever, as per CFRunLoop.c */
} else {
waitTime = myTimePtr->sec + 1.0e-6 * myTimePtr->usec;
}
+ /*
+ * If the run loop is already running (e.g. if Tcl_WaitForEvent was
+ * called recursively), re-run it in a custom run loop mode containing
+ * only the source for the notifier thread, otherwise wakeups from other
+ * sources added to the common run loop modes might get lost.
+ */
+ if ((runLoopMode = CFRunLoopCopyCurrentMode(tsdPtr->runLoop))) {
+ CFRelease(runLoopMode);
+ runLoopMode = tclEventsOnlyRunLoopMode;
+ } else {
+ runLoopMode = kCFRunLoopDefaultMode;
+ }
UNLOCK_NOTIFIER;
- CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, TRUE);
+ CFRunLoopRunInMode(runLoopMode, waitTime, TRUE);
LOCK_NOTIFIER;
}
tsdPtr->eventReady = 0;