From f4c863c6aa502bbc5309aac91c21835f388afad6 Mon Sep 17 00:00:00 2001 From: Allan Odgaard Date: Wed, 22 Apr 2020 22:27:29 +0700 Subject: [PATCH] Use a GCD source for observing sockets instead of CFSocket This is motivated by having received several crash reports from CFSocketManager over the years, example crash log from TextMate 2.0.8: Thread 5 Crashed:: com.apple.CFSocket.private 0 libsystem_kernel.dylib os_fault_with_payload + 10 1 libsystem_kernel.dylib __darwin_check_fd_set_overflow.cold.1 + 31 2 libsystem_kernel.dylib __darwin_check_fd_set_overflow + 79 3 com.apple.CoreFoundation __CFSocketManager + 939 4 libsystem_pthread.dylib _pthread_start + 148 5 libsystem_pthread.dylib thread_start + 15 --- Applications/TextMate/src/RMateServer.mm | 36 ++++++------------------ 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/Applications/TextMate/src/RMateServer.mm b/Applications/TextMate/src/RMateServer.mm index 603d9f2f..8986d7e3 100644 --- a/Applications/TextMate/src/RMateServer.mm +++ b/Applications/TextMate/src/RMateServer.mm @@ -47,40 +47,21 @@ struct socket_callback_t helper = std::make_shared(f, fd, this); - CFSocketContext const context = { 0, helper.get(), NULL, NULL, NULL }; - if(socket = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, callback, &context)) + if(_dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (int)fd, 0, dispatch_get_main_queue())) { - CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate); - if(run_loop_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0)) - CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopDefaultMode); - else fprintf(stderr, "*** CFSocketCreateRunLoopSource() failed\n"); - } - else - { - fprintf(stderr, "*** CFSocketCreateWithNative() failed: fd = %d\n", (int)fd); + dispatch_source_set_event_handler(_dispatchSource, ^{ + (*helper)(); + }); + dispatch_resume(_dispatchSource); } } ~socket_callback_t () { D(DBF_RMateServer, bug("%p\n", this);); - ASSERT(CFRunLoopContainsSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopDefaultMode)); - if(socket) - { - CFSocketInvalidate(socket); - if(run_loop_source) - { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopDefaultMode); - CFRelease(run_loop_source); - } - CFRelease(socket); - } - } - - static void callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, void const* data, void* info) - { - (*(helper_t*)info)(); + if(_dispatchSource) + dispatch_source_cancel(_dispatchSource); } private: @@ -96,8 +77,7 @@ private: }; std::shared_ptr helper; - CFSocketRef socket; - CFRunLoopSourceRef run_loop_source; + dispatch_source_t _dispatchSource; }; typedef std::shared_ptr socket_callback_ptr;