changeset 79509:e4c75e9b905b

(cfsockets_for_select) [MAC_OSX && SELECT_USE_CFSOCKET]: New variable. (mac_try_close_socket) [MAC_OSX]: New function. [MAC_OSX] (sys_select) [SELECT_USE_CFSOCKET]: Update cfsockets_for_select. Replace invalid CFRunLoop source.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Fri, 30 Nov 2007 08:19:36 +0000
parents 226de5ee19d3
children f5153b60663d
files src/mac.c
diffstat 1 files changed, 49 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/mac.c	Thu Nov 29 22:36:17 2007 +0000
+++ b/src/mac.c	Fri Nov 30 08:19:36 2007 +0000
@@ -5009,6 +5009,10 @@
 #if SELECT_USE_CFSOCKET
 #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
 
+/* Dictionary of file descriptors vs CFSocketRef's allocated in
+   sys_select.  */
+static CFMutableDictionaryRef cfsockets_for_select;
+
 static void
 socket_callback (s, type, address, data, info)
      CFSocketRef s;
@@ -5078,6 +5082,43 @@
     return 0;
 }
 
+/* Clean up the CFSocket associated with the file descriptor FD in
+   case the same descriptor is used in other threads later.  If no
+   CFSocket is associated with FD, then return 0 without closing FD.
+   Otherwise, return 1 with closing FD.  */
+
+int
+mac_try_close_socket (fd)
+     int fd;
+{
+#if SELECT_USE_CFSOCKET
+  if (cfsockets_for_select)
+    {
+      void *key = (void *) fd;
+      CFSocketRef socket =
+	(CFSocketRef) CFDictionaryGetValue (cfsockets_for_select, key);
+
+      if (socket)
+	{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+	  CFOptionFlags flags = CFSocketGetSocketFlags (socket);
+
+	  if (!(flags & kCFSocketCloseOnInvalidate))
+	    CFSocketSetSocketFlags (socket, flags | kCFSocketCloseOnInvalidate);
+#endif
+	  BLOCK_INPUT;
+	  CFSocketInvalidate (socket);
+	  CFDictionaryRemoveValue (cfsockets_for_select, key);
+	  UNBLOCK_INPUT;
+
+	  return 1;
+	}
+    }
+#endif
+
+  return 0;
+}
+
 int
 sys_select (nfds, rfds, wfds, efds, timeout)
      int nfds;
@@ -5156,6 +5197,11 @@
 	      CFDictionaryCreateMutable (NULL, 0, NULL,
 					 &kCFTypeDictionaryValueCallBacks);
 
+	  if (cfsockets_for_select == NULL)
+	    cfsockets_for_select =
+	      CFDictionaryCreateMutable (NULL, 0, NULL,
+					 &kCFTypeDictionaryValueCallBacks);
+
 	  for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel.  */
 	    if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds)))
 	      break;
@@ -5167,7 +5213,7 @@
 		CFRunLoopSourceRef source =
 		  (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
 
-		if (source == NULL)
+		if (source == NULL || !CFRunLoopSourceIsValid (source))
 		  {
 		    CFSocketRef socket =
 		      CFSocketCreateWithNative (NULL, fd,
@@ -5177,11 +5223,12 @@
 
 		    if (socket == NULL)
 		      continue;
+		    CFDictionarySetValue (cfsockets_for_select, key, socket);
 		    source = CFSocketCreateRunLoopSource (NULL, socket, 0);
 		    CFRelease (socket);
 		    if (source == NULL)
 		      continue;
-		    CFDictionaryAddValue (sources, key, source);
+		    CFDictionarySetValue (sources, key, source);
 		    CFRelease (source);
 		  }
 		CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);