From: Apple Date: Mon, 15 Nov 2010 19:15:33 +0000 (+0000) Subject: CF-550.42.tar.gz X-Git-Tag: mac-os-x-1065^0 X-Git-Url: https://git.saurik.com/apple/cf.git/commitdiff_plain/7c97c3e0372470105800578fb90281b94a3cfd02?ds=inline CF-550.42.tar.gz --- diff --git a/BuildCFLite b/BuildCFLite index 7bc3eea..cc606d2 100755 --- a/BuildCFLite +++ b/BuildCFLite @@ -25,9 +25,9 @@ PUBLIC_HEADERS="CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFBundle PRIVATE_HEADERS="CFBundlePriv.h CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStreamAbstract.h CFStreamPriv.h CFStreamInternal.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h" OBJBASE=./CF-Objects -ARCHFLAGS="-arch i386 -arch x86_64" -CFLAGS="-c -x objective-c -pipe -std=gnu99 -g -Wmost -Wno-trigraphs -mmacosx-version-min=10.6 -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_6 -DU_SHOW_DRAFT_API=1 -I$OBJBASE -DVERSION=550.13 -include CoreFoundation_Prefix.h" -LFLAGS="-dynamiclib -mmacosx-version-min=10.6 -twolevel_namespace -init ___CFInitialize -compatibility_version 150 -current_version 550.13 -sectcreate __UNICODE __csbitmaps CFCharacterSetBitmaps.bitmap -Wl,-alias_list,SymbolAliases -sectcreate __UNICODE __properties CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data $UNICODE_DATA_FILE -segprot __UNICODE r r" +ARCHFLAGS="-arch ppc -arch i386 -arch x86_64" +CFLAGS="-c -x objective-c -pipe -std=gnu99 -g -Wmost -Wno-trigraphs -mmacosx-version-min=10.6 -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_6 -DU_SHOW_DRAFT_API=1 -I$OBJBASE -DVERSION=535 -include CoreFoundation_Prefix.h" +LFLAGS="-dynamiclib -mmacosx-version-min=10.6 -twolevel_namespace -init ___CFInitialize -compatibility_version 150 -current_version 535 -sectcreate __UNICODE __csbitmaps CFCharacterSetBitmaps.bitmap -sectcreate __UNICODE __properties CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data $UNICODE_DATA_FILE -segprot __UNICODE r r" /bin/rm -rf $OBJBASE /bin/mkdir -p $OBJBASE diff --git a/CFBase.h b/CFBase.h index b046940..c1e1590 100644 --- a/CFBase.h +++ b/CFBase.h @@ -219,12 +219,21 @@ CF_EXPORT double kCFCoreFoundationVersionNumber; #define kCFCoreFoundationVersionNumber10_5_4 476.14 #define kCFCoreFoundationVersionNumber10_5_5 476.15 #define kCFCoreFoundationVersionNumber10_5_6 476.17 +#define kCFCoreFoundationVersionNumber10_5_7 476.18 +#define kCFCoreFoundationVersionNumber10_5_8 476.19 +#define kCFCoreFoundationVersionNumber10_6 550.00 +#define kCFCoreFoundationVersionNumber10_6_1 550.00 +#define kCFCoreFoundationVersionNumber10_6_2 550.13 +#define kCFCoreFoundationVersionNumber10_6_3 550.19 #endif #if TARGET_OS_IPHONE #define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23 #define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26 #define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29 +#define kCFCoreFoundationVersionNumber_iPhoneOS_3_0 478.47 +#define kCFCoreFoundationVersionNumber_iPhoneOS_3_1 478.52 +#define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61 #endif typedef unsigned long CFTypeID; diff --git a/CFInternal.h b/CFInternal.h index aa1228a..7f8d9a6 100644 --- a/CFInternal.h +++ b/CFInternal.h @@ -75,6 +75,7 @@ CF_EXTERN_C_BEGIN #define __CF_BIG_ENDIAN__ 0 #endif + #include CF_EXPORT const char *_CFProcessName(void); @@ -345,8 +346,8 @@ const CFStringRef S = (CFStringRef) & __ ## S ## __; #define PE_CONST_STRING_DECL(S, V) \ static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)(V), sizeof(V) - 1}; \ __private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __; +#endif #endif // __BIG_ENDIAN__ -#endif // __CONSTANT_CFSTRINGS__ /* Buffer size for file pathname */ @@ -548,23 +549,68 @@ CF_INLINE Boolean CF_IS_OBJC(CFTypeID typeID, const void *obj) { return (typeID >= __CFRuntimeClassTableSize) || (((CFRuntimeBase *)obj)->_cfisa != __CFISAForTypeID(typeID) && ((CFRuntimeBase *)obj)->_cfisa > (uintptr_t)0xFFF); } - -#define CF_IS_OBJC(typeID, obj) (false) - -#define CF_OBJC_VOIDCALL0(obj, sel) -#define CF_OBJC_VOIDCALL1(obj, sel, a1) -#define CF_OBJC_VOIDCALL2(obj, sel, a1, a2) - -#define CF_OBJC_CALL0(rettype, retvar, obj, sel) -#define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1) -#define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2) - -#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) -#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1) -#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2) -#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3) -#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4) -#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5) +// Invoke an ObjC method that returns void. +// Assumes CF_IS_OBJC has already been checked. +#define CF_OBJC_VOIDCALL0(obj, sel) \ + {void (*func)(const void *, SEL) = (void (*)(const void *, SEL))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + func((const void *)obj, s);} +#define CF_OBJC_VOIDCALL1(obj, sel, a1) \ + {void (*func)(const void *, SEL, ...) = (void (*)(const void *, SEL, ...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + func((const void *)obj, s, (a1));} +#define CF_OBJC_VOIDCALL2(obj, sel, a1, a2) \ + {void (*func)(const void *, SEL, ...) = (void (*)(const void *, SEL, ...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + func((const void *)obj, s, (a1), (a2));} + + +// Invoke an ObjC method, leaving the result in "retvar". +// Assumes CF_IS_OBJC has already been checked. +#define CF_OBJC_CALL0(rettype, retvar, obj, sel) \ + {rettype (*func)(const void *, SEL) = (rettype (*)(const void *, SEL))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + retvar = func((const void *)obj, s);} +#define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL, ...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + retvar = func((const void *)obj, s, (a1));} +#define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL, ...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + retvar = func((const void *)obj, s, (a1), (a2));} + +// Invoke an ObjC method, return the result +#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL) = (rettype (*)(const void *, SEL))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s);} +#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s, (a1));} +#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s, (a1), (a2));} +#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s, (a1), (a2), (a3));} +#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s, (a1), (a2), (a3), (a4));} +#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5) \ + if (__builtin_expect(CF_IS_OBJC(typeID, obj), 0)) \ + {rettype (*func)(const void *, SEL, ...) = (rettype (*)(const void *, SEL,...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((const void *)obj, s, (a1), (a2), (a3), (a4), (a5));} #endif diff --git a/CFLocaleKeys.m b/CFLocaleKeys.m index 5e5ec12..ac19d7a 100644 --- a/CFLocaleKeys.m +++ b/CFLocaleKeys.m @@ -29,6 +29,7 @@ NSString * const kCFLocaleAlternateQuotationEndDelimiterKey = @"kCFLocaleAlterna NSString * const kCFLocaleQuotationBeginDelimiterKey = @"kCFLocaleQuotationBeginDelimiterKey"; NSString * const kCFLocaleQuotationEndDelimiterKey = @"kCFLocaleQuotationEndDelimiterKey"; NSString * const kCFLocaleCalendarIdentifierKey = @"calendar"; // *** +NSString * const kCFLocaleCalendarIdentifier = @"calendar"; // *** NSString * const kCFLocaleCalendarKey = @"kCFLocaleCalendarKey"; NSString * const kCFLocaleCollationIdentifierKey = @"collation"; // *** NSString * const kCFLocaleCollatorIdentifierKey = @"kCFLocaleCollatorIdentifierKey"; @@ -68,6 +69,7 @@ NSString * const kCFDateFormatterStandaloneMonthSymbolsKey = @"kCFDateFormatterS NSString * const kCFDateFormatterStandaloneQuarterSymbolsKey = @"kCFDateFormatterStandaloneQuarterSymbolsKey"; NSString * const kCFDateFormatterStandaloneWeekdaySymbolsKey = @"kCFDateFormatterStandaloneWeekdaySymbolsKey"; NSString * const kCFDateFormatterTimeZoneKey = @"kCFDateFormatterTimeZoneKey"; +NSString * const kCFDateFormatterTimeZone = @"kCFDateFormatterTimeZoneKey"; NSString * const kCFDateFormatterTwoDigitStartDateKey = @"kCFDateFormatterTwoDigitStartDateKey"; NSString * const kCFDateFormatterVeryShortMonthSymbolsKey = @"kCFDateFormatterVeryShortMonthSymbolsKey"; NSString * const kCFDateFormatterVeryShortStandaloneMonthSymbolsKey = @"kCFDateFormatterVeryShortStandaloneMonthSymbolsKey"; @@ -128,3 +130,15 @@ NSString * const kCFCalendarIdentifierISO8601 = @""; NSString * const kCFCalendarIdentifierCoptic = @"coptic"; NSString * const kCFCalendarIdentifierEthiopicAmeteMihret = @"ethiopic"; NSString * const kCFCalendarIdentifierEthiopicAmeteAlem = @"ethiopic-amete-alem"; + +NSString * const kCFGregorianCalendar = @"gregorian"; +NSString * const kCFBuddhistCalendar = @"buddhist"; +NSString * const kCFChineseCalendar = @"chinese"; +NSString * const kCFHebrewCalendar = @"hebrew"; +NSString * const kCFIslamicCalendar = @"islamic"; +NSString * const kCFIslamicCivilCalendar = @"islamic-civil"; +NSString * const kCFJapaneseCalendar = @"japanese"; +NSString * const kCFRepublicOfChinaCalendar = @"roc"; +NSString * const kCFPersianCalendar = @"persian"; +NSString * const kCFIndianCalendar = @"indian"; +NSString * const kCFISO8601Calendar = @""; diff --git a/CFMachPort.c b/CFMachPort.c index abdf281..5f9cbb5 100644 --- a/CFMachPort.c +++ b/CFMachPort.c @@ -22,7 +22,7 @@ */ /* CFMachPort.c - Copyright (c) 1998-2009, Apple Inc. All rights reserved. + Copyright (c) 1998-2010, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -37,6 +37,10 @@ #define AVOID_WEAK_COLLECTIONS 1 +#if DEPLOYMENT_TARGET_EMBEDDED +#define AVOID_WEAK_COLLECTIONS 1 +#endif + #if !defined(AVOID_WEAK_COLLECTIONS) #import "CFPointerArray.h" #endif @@ -185,7 +189,7 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { dispatch_semaphore_t sem2 = mp->_dsrc2_sem; Boolean doSend2 = __CFMachPortHasSend2(mp), doSend = __CFMachPortHasSend(mp), doReceive = __CFMachPortHasReceive(mp); - dispatch_async(dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_LOW), ^{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ if (sem1) { dispatch_semaphore_wait(sem1, DISPATCH_TIME_FOREVER); // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit @@ -330,18 +334,13 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p static Boolean portCheckerGoing = false; if (!portCheckerGoing) { uint64_t nanos = 63 * 1000 * 1000 * 1000ULL; - uint64_t leeway = 9; - (void)dispatch_source_timer_create(DISPATCH_TIMER_INTERVAL, nanos, leeway, NULL, __portQueue(), ^(dispatch_source_t source) { - long e = 0, d = dispatch_source_get_error(source, &e); - if (DISPATCH_ERROR_DOMAIN_POSIX == d && ECANCELED == e) { - dispatch_release(source); - return; - } - if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) { - HALT; - } - __CFMachPortChecker(true); - }); + uint64_t leeway = 9 * 1000ULL; + dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __portQueue()); + dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, nanos), nanos, leeway); + dispatch_source_set_event_handler(timerSource, ^{ + __CFMachPortChecker(true); + }); + dispatch_resume(timerSource); portCheckerGoing = true; } @@ -398,34 +397,15 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p if (shouldFreeInfo) *shouldFreeInfo = false; if (type & MACH_PORT_TYPE_SEND_RIGHTS) { - memory->_dsrc = dispatch_source_machport_create(port, DISPATCH_MACHPORT_DEAD, NULL, __portQueue(), ^(dispatch_source_t source) { - long e = 0, d = dispatch_source_get_error(source, &e); - if (DISPATCH_ERROR_DOMAIN_MACH == d) { - CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-dead dispatch source provided error (%d, %d)"), d, e); - dispatch_release(source); - return; - } - if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) { - CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-dead dispatch source provided error (%d, %d)"), d, e); - HALT; - } - __CFMachPortChecker(false); - }); - } - if ((type & MACH_PORT_TYPE_RECEIVE) && !(type & MACH_PORT_TYPE_SEND_RIGHTS)) { - memory->_dsrc2 = dispatch_source_machport_create(port, DISPATCH_MACHPORT_DELETED, NULL, __portQueue(), ^(dispatch_source_t source) { - long e = 0, d = dispatch_source_get_error(source, &e); - if (DISPATCH_ERROR_DOMAIN_MACH == d) { - CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-deleted dispatch source provided error (%d, %d)"), d, e); - dispatch_release(source); - return; - } - if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) { - CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-deleted dispatch source provided error (%d, %d)"), d, e); - HALT; - } - __CFMachPortChecker(false); - }); + dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, port, DISPATCH_MACH_SEND_DEAD, __portQueue()); + dispatch_source_set_cancel_handler(theSource, ^{ + dispatch_release(theSource); + }); + dispatch_source_set_event_handler(theSource, ^{ + __CFMachPortChecker(false); + }); + memory->_dsrc = theSource; + dispatch_resume(theSource); } if (memory->_dsrc) { dispatch_source_t source = memory->_dsrc; // put these in locals so they are fully copied into the block @@ -440,6 +420,10 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p dispatch_source_set_cancel_handler(memory->_dsrc2, ^{ dispatch_semaphore_signal(sem); dispatch_release(source); }); } }); + if (mp && !CFMachPortIsValid(mp)) { // must do this outside lock to avoid deadlock + CFRelease(mp); + mp = NULL; + } return mp; } @@ -547,7 +531,18 @@ void CFMachPortGetContext(CFMachPortRef mp, CFMachPortContext *context) { Boolean CFMachPortIsValid(CFMachPortRef mp) { CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), Boolean, mp, "isValid"); __CFGenericValidateType(mp, CFMachPortGetTypeID()); - return __CFMachPortIsValid(mp); + if (!__CFMachPortIsValid(mp)) return false; + mach_port_type_t type = 0; + kern_return_t ret = mach_port_type(mach_task_self(), mp->_port, &type); + if (KERN_SUCCESS != ret || (type & ~(MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_SEND_ONCE|MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_DNREQUEST))) { + CFRetain(mp); + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + CFMachPortInvalidate(mp); + CFRelease(mp); + }); + return false; + } + return true; } CFMachPortInvalidationCallBack CFMachPortGetInvalidationCallBack(CFMachPortRef mp) { @@ -614,9 +609,14 @@ static void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocat CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMachPortRef mp, CFIndex order) { CHECK_FOR_FORK_RET(NULL); __CFGenericValidateType(mp, CFMachPortGetTypeID()); + if (!CFMachPortIsValid(mp)) return NULL; __block CFRunLoopSourceRef result = NULL; dispatch_sync(__portQueue(), ^{ if (!__CFMachPortIsValid(mp)) return; + if (NULL != mp->_source && !CFRunLoopSourceIsValid(mp->_source)) { + CFRelease(mp->_source); + mp->_source = NULL; + } if (NULL == mp->_source) { CFRunLoopSourceContext1 context; context.version = 1; diff --git a/CFMessagePort.c b/CFMessagePort.c index 569b6a0..40afce5 100644 --- a/CFMessagePort.c +++ b/CFMessagePort.c @@ -22,7 +22,7 @@ */ /* CFMessagePort.c - Copyright (c) 1998-2009, Apple Inc. All rights reserved. + Copyright (c) 1998-2010, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -174,8 +174,8 @@ static mach_msg_base_t *__CFMessagePortCreateMessage(bool reply, mach_port_t por if (rounded_byteslen <= __CFMessagePortMaxInlineBytes) { int32_t size = sizeof(struct __CFMessagePortMachMessage0) + rounded_byteslen; struct __CFMessagePortMachMessage0 *msg = CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0); - if (!msg) return NULL; - memset(msg, 0, size); + if (!msg) return NULL; + memset(msg, 0, size); msg->base.header.msgh_id = convid; msg->base.header.msgh_size = size; msg->base.header.msgh_remote_port = port; @@ -184,8 +184,8 @@ static mach_msg_base_t *__CFMessagePortCreateMessage(bool reply, mach_port_t por msg->base.header.msgh_bits = MACH_MSGH_BITS((reply ? MACH_MSG_TYPE_MOVE_SEND_ONCE : MACH_MSG_TYPE_COPY_SEND), (MACH_PORT_NULL != replyPort ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0)); msg->base.body.msgh_descriptor_count = 0; msg->magic = MAGIC; - msg->msgid = CFSwapInt32HostToLittle(msgid); - msg->byteslen = CFSwapInt32HostToLittle(byteslen); + msg->msgid = CFSwapInt32HostToLittle(msgid); + msg->byteslen = CFSwapInt32HostToLittle(byteslen); if (NULL != bytes && 0 < byteslen) { memmove(msg->bytes, bytes, byteslen); } @@ -360,6 +360,10 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS __CFSpinUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); + if (!CFMessagePortIsValid(existing)) { // must do this outside lock to avoid deadlock + CFRelease(existing); + existing = NULL; + } return (CFMessagePortRef)(existing); } } @@ -495,6 +499,10 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF __CFSpinUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); + if (!CFMessagePortIsValid(existing)) { // must do this outside lock to avoid deadlock + CFRelease(existing); + existing = NULL; + } return (CFMessagePortRef)(existing); } } @@ -694,7 +702,7 @@ void CFMessagePortInvalidate(CFMessagePortRef ms) { __CFMessagePortLock(ms); if (__CFMessagePortIsValid(ms)) { if (ms->_dispatchSource) { - dispatch_cancel(ms->_dispatchSource); + dispatch_source_cancel(ms->_dispatchSource); ms->_dispatchSource = NULL; ms->_dispatchQ = NULL; } @@ -764,10 +772,6 @@ Boolean CFMessagePortIsValid(CFMessagePortRef ms) { CFMessagePortInvalidate(ms); return false; } - if (NULL != ms->_source && !CFRunLoopSourceIsValid(ms->_source)) { - CFMessagePortInvalidate(ms); - return false; - } return true; } @@ -1068,9 +1072,13 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef ms, CFIndex order) { CFRunLoopSourceRef result = NULL; __CFGenericValidateType(ms, __kCFMessagePortTypeID); -//#warning CF: This should be an assert - // if (__CFMessagePortIsRemote(ms)) return NULL; + if (!CFMessagePortIsValid(ms)) return NULL; + if (__CFMessagePortIsRemote(ms)) return NULL; __CFMessagePortLock(ms); + if (NULL != ms->_source && !CFRunLoopSourceIsValid(ms->_source)) { + CFRelease(ms->_source); + ms->_source = NULL; + } if (NULL == ms->_source && NULL == ms->_dispatchSource && __CFMessagePortIsValid(ms)) { CFRunLoopSourceContext1 context; context.version = 1; @@ -1111,7 +1119,7 @@ void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) } if (ms->_dispatchSource) { - dispatch_cancel(ms->_dispatchSource); + dispatch_source_cancel(ms->_dispatchSource); ms->_dispatchSource = NULL; ms->_dispatchQ = NULL; } @@ -1119,49 +1127,44 @@ void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) if (queue) { mach_port_t port = __CFMessagePortGetPort(ms); if (MACH_PORT_NULL != port) { - ms->_dispatchSource = dispatch_source_machport_create(port, DISPATCH_MACHPORT_RECV, DISPATCH_SOURCE_CREATE_SUSPENDED, __mportQueue(), ^(dispatch_source_t source) { - long e = 0, d = dispatch_source_get_error(source, &e); - if (DISPATCH_ERROR_DOMAIN_POSIX == d && ECANCELED == e) { - dispatch_release(queue); - dispatch_release(source); - return; - } - if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) { - HALT; - } - - CFRetain(ms); - mach_port_t port = dispatch_source_get_handle(source); - mach_msg_header_t *msg = (mach_msg_header_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2048, 0); - msg->msgh_size = 2048; - - for (;;) { - msg->msgh_bits = 0; - msg->msgh_local_port = port; - msg->msgh_remote_port = MACH_PORT_NULL; - msg->msgh_id = 0; - - kern_return_t ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, 0, MACH_PORT_NULL); - if (MACH_MSG_SUCCESS == ret) break; - if (MACH_RCV_TOO_LARGE != ret) HALT; - - uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE); - msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0); - msg->msgh_size = newSize; - } - - dispatch_async(queue, ^{ - mach_msg_header_t *reply = __CFMessagePortPerform(msg, msg->msgh_size, kCFAllocatorSystemDefault, ms); - if (NULL != reply) { - kern_return_t ret = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); - if (KERN_SUCCESS != ret) mach_msg_destroy(reply); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply); - } - CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg); - CFRelease(ms); - }); - }); - } + dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, __mportQueue()); + dispatch_source_set_cancel_handler(theSource, ^{ + dispatch_release(queue); + dispatch_release(theSource); + }); + dispatch_source_set_event_handler(theSource, ^{ + CFRetain(ms); + mach_msg_header_t *msg = (mach_msg_header_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2048, 0); + msg->msgh_size = 2048; + + for (;;) { + msg->msgh_bits = 0; + msg->msgh_local_port = port; + msg->msgh_remote_port = MACH_PORT_NULL; + msg->msgh_id = 0; + + kern_return_t ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, 0, MACH_PORT_NULL); + if (MACH_MSG_SUCCESS == ret) break; + if (MACH_RCV_TOO_LARGE != ret) HALT; + + uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE); + msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0); + msg->msgh_size = newSize; + } + + dispatch_async(queue, ^{ + mach_msg_header_t *reply = __CFMessagePortPerform(msg, msg->msgh_size, kCFAllocatorSystemDefault, ms); + if (NULL != reply) { + kern_return_t ret = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); + if (KERN_SUCCESS != ret) mach_msg_destroy(reply); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply); + } + CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg); + CFRelease(ms); + }); + }); + ms->_dispatchSource = theSource; + } if (ms->_dispatchSource) { dispatch_retain(queue); ms->_dispatchQ = queue; diff --git a/CFRuntime.c b/CFRuntime.c index 1c5c2aa..92a8193 100644 --- a/CFRuntime.c +++ b/CFRuntime.c @@ -470,11 +470,31 @@ __private_extern__ void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, co #define __CFGenericAssertIsCF(cf) \ CFAssert2(cf != NULL && (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]) && (__kCFNotATypeTypeID != __CFGenericTypeID_inline(cf)) && (__kCFTypeTypeID != __CFGenericTypeID_inline(cf)), __kCFLogAssertion, "%s(): pointer %p is not a CF object", __PRETTY_FUNCTION__, cf); +#if 0 #define CFTYPE_IS_OBJC(obj) (false) #define CFTYPE_OBJC_FUNCDISPATCH0(rettype, obj, sel) do {} while (0) #define CFTYPE_OBJC_FUNCDISPATCH1(rettype, obj, sel, a1) do {} while (0) +#else + +CF_INLINE int CFTYPE_IS_OBJC(const void *obj) { + CFTypeID typeID = __CFGenericTypeID_inline(obj); + return CF_IS_OBJC(typeID, obj); +} + +#define CFTYPE_OBJC_FUNCDISPATCH0(rettype, obj, sel) \ + if (CFTYPE_IS_OBJC(obj)) \ + {rettype (*func)(void *, SEL) = (rettype (*)(void *, SEL))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((void *)obj, s);} +#define CFTYPE_OBJC_FUNCDISPATCH1(rettype, obj, sel, a1) \ + if (CFTYPE_IS_OBJC(obj)) \ + {rettype (*func)(void *, SEL, ...) = (rettype (*)(void *, SEL, ...))objc_msgSend; \ + static SEL s = NULL; if (!s) s = sel_registerName(sel); \ + return func((void *)obj, s, (a1));} + +#endif CFTypeID CFGetTypeID(CFTypeRef cf) { #if defined(DEBUG) @@ -1262,7 +1282,7 @@ CF_EXPORT CFTypeRef _CFRetain(CFTypeRef cf) { } while (__builtin_expect(!success, 0)); #endif if (!didAuto && __builtin_expect(__CFOASafe, 0)) { - __CFRecordAllocationEvent(__kCFRetainEvent, (void *)cf, 0, 0, NULL); + __CFRecordAllocationEvent(__kCFRetainEvent, (void *)cf, 0, CFGetRetainCount(cf), NULL); } return cf; } @@ -1380,7 +1400,7 @@ CF_EXPORT void _CFRelease(CFTypeRef cf) { #endif if (!didAuto && __builtin_expect(__CFOASafe, 0)) { - __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, 0, NULL); + __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, CFGetRetainCount(cf), NULL); } return; diff --git a/CFSocket.c b/CFSocket.c index bf049f7..7a6e472 100644 --- a/CFSocket.c +++ b/CFSocket.c @@ -22,7 +22,7 @@ */ /* CFSocket.c - Copyright (c) 1999-2009, Apple Inc. All rights reserved. + Copyright (c) 1999-2010, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -39,7 +39,9 @@ #include #include #include +#include #include +#include extern void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls); @@ -50,6 +52,38 @@ extern void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls); DISPATCH_HELPER_FUNCTIONS(sock, CFSocket) +static Boolean sockfd_is_readable(int fd) { + if (fd < 0 || 1048576 <= fd) HALT; + size_t sz = ((fd + CHAR_BIT) / CHAR_BIT) + 7; // generous + fd_set *fdset = malloc(sz); + int ret; + do { + memset(fdset, 0, sz); + FD_SET(fd, fdset); + struct timespec ts = {0, 1000UL}; // 1 us + ret = pselect(fd + 1, fdset, NULL, NULL, &ts, NULL); + } while (ret < 0 && (EINTR == errno || EAGAIN == errno)); + Boolean isSet = ((0 < ret) && FD_ISSET(fd, fdset)); + free(fdset); + return isSet; +} + +static Boolean sockfd_is_writeable(int fd) { + if (fd < 0 || 1048576 <= fd) HALT; + size_t sz = ((fd + CHAR_BIT) / CHAR_BIT) + 7; // generous + fd_set *fdset = malloc(sz); + int ret; + do { + memset(fdset, 0, sz); + FD_SET(fd, fdset); + struct timespec ts = {0, 1000UL}; // 1 us + ret = pselect(fd + 1, NULL, fdset, NULL, &ts, NULL); + } while (ret < 0 && (EINTR == errno || EAGAIN == errno)); + Boolean isSet = ((0 < ret) && FD_ISSET(fd, fdset)); + free(fdset); + return isSet; +} + enum { kCFSocketStateReady = 0, @@ -84,11 +118,11 @@ struct __CFSocket { uint8_t _wsuspended:1; uint8_t _readable:1; uint8_t _writeable:1; - uint8_t _unused2:4; + uint8_t _unused:4; uint8_t _reenableRead:1; uint8_t _readDisabled:1; - uint8_t _reeanbleWrite:1; + uint8_t _reenableWrite:1; uint8_t _writeDisabled:1; uint8_t _connectDisabled:1; uint8_t _connected:1; @@ -132,7 +166,7 @@ static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) { "source = %p, callout = %s (%p), context = %@}"), cf, CFGetAllocator(sock), __CFSocketIsValid(sock) ? "Yes" : "No", sock->_shared ? sock->_shared->_socket : -1, sock->_wantConnect ? "Yes" : "No", sock->_connectDisabled ? "Yes" : "No", - sock->_wantWrite ? "Yes" : "No", sock->_reeanbleWrite ? "Yes" : "No", sock->_writeDisabled ? "Yes" : "No", + sock->_wantWrite ? "Yes" : "No", sock->_reenableWrite ? "Yes" : "No", sock->_writeDisabled ? "Yes" : "No", sock->_wantReadType ? "Yes" : "No", sock->_reenableRead ? "Yes" : "No", sock->_readDisabled? "Yes" : "No", sock->_leaveErrors ? "Yes" : "No", sock->_closeOnInvalidate ? "Yes" : "No", sock->_connected ? "Yes" : "No", sock->_error, avail, @@ -209,7 +243,7 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan if (INVALID_SOCKET != ufd) { uint32_t type = (statbuf.st_mode & S_IFMT); sane = (S_IFSOCK == type) || (S_IFIFO == type) || (S_IFCHR == type); - if (0 && !sane) { + if (1 && !sane) { CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with silly fd type (%07o) -- may or may not work"), type); } } @@ -225,7 +259,7 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan canHandle = (0 <= ret); // if kevent(ADD) succeeds, can handle close(tmp_kq); } - if (0 && !canHandle) { + if (1 && !canHandle) { CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with unsupported fd type -- may or may not work")); } } @@ -276,7 +310,7 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan memory->_reenableRead = memory->_wantReadType ? true : false; memory->_readDisabled = false; memory->_wantWrite = (callBackTypes & kCFSocketWriteCallBack) ? true : false; - memory->_reeanbleWrite = false; + memory->_reenableWrite = false; memory->_writeDisabled = false; memory->_wantConnect = (callBackTypes & kCFSocketConnectCallBack) ? true : false; memory->_connectDisabled = false; @@ -320,6 +354,7 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan memory->_readable = true; if (!memory->_rsuspended) { dispatch_suspend(dsrc); +// CFLog(5, CFSTR("suspend %p due to read event block"), memory); memory->_rsuspended = true; } if (shared->_source) { @@ -331,7 +366,14 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan shared->_rdsrc = NULL; shared->_refCnt--; if (0 == shared->_refCnt) { - if (shared->_closeFD) close(shared->_socket); + if (shared->_closeFD) { + // thoroughly stop anything else from using the fd + (void)shutdown(shared->_socket, SHUT_RDWR); + int nullfd = open("/dev/null", O_RDONLY); + dup2(nullfd, shared->_socket); + close(nullfd); + close(shared->_socket); + } free(shared); } dispatch_release(dsrc); @@ -352,6 +394,7 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan memory->_writeable = true; if (!memory->_wsuspended) { dispatch_suspend(dsrc); +// CFLog(5, CFSTR("suspend %p due to write event block"), memory); memory->_wsuspended = true; } if (shared->_source) { @@ -363,7 +406,14 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan shared->_wrsrc = NULL; shared->_refCnt--; if (0 == shared->_refCnt) { - if (shared->_closeFD) close(shared->_socket); + if (shared->_closeFD) { + // thoroughly stop anything else from using the fd + (void)shutdown(shared->_socket, SHUT_RDWR); + int nullfd = open("/dev/null", O_RDONLY); + dup2(nullfd, shared->_socket); + close(nullfd); + close(shared->_socket); + } free(shared); } dispatch_release(dsrc); @@ -385,6 +435,10 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan sock = memory; }); // CFLog(5, CFSTR("CFSocketCreateWithNative(): created socket %p with callbacks 0x%x"), sock, callBackTypes); + if (sock && !CFSocketIsValid(sock)) { // must do this outside lock to avoid deadlock + CFRelease(sock); + sock = NULL; + } return sock; } @@ -408,7 +462,7 @@ CFDataRef CFSocketCopyAddress(CFSocketRef sock) { if (!sock->_address) { if (!__CFSocketIsValid(sock)) return; uint8_t name[MAX_SOCKADDR_LEN]; - int namelen = sizeof(name); + socklen_t namelen = sizeof(name); int ret = getsockname(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen); if (0 == ret && 0 < namelen) { sock->_address = CFDataCreate(CFGetAllocator(sock), name, namelen); @@ -416,7 +470,6 @@ CFDataRef CFSocketCopyAddress(CFSocketRef sock) { } result = sock->_address ? (CFDataRef)CFRetain(sock->_address) : NULL; }); -// CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p address %@"), sock, result); return result; } @@ -428,7 +481,7 @@ CFDataRef CFSocketCopyPeerAddress(CFSocketRef sock) { if (!sock->_peerAddress) { if (!__CFSocketIsValid(sock)) return; uint8_t name[MAX_SOCKADDR_LEN]; - int namelen = sizeof(name); + socklen_t namelen = sizeof(name); int ret = getpeername(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen); if (0 == ret && 0 < namelen) { sock->_peerAddress = CFDataCreate(CFGetAllocator(sock), name, namelen); @@ -436,7 +489,6 @@ CFDataRef CFSocketCopyPeerAddress(CFSocketRef sock) { } result = sock->_peerAddress ? (CFDataRef)CFRetain(sock->_peerAddress) : NULL; }); -// CFLog(5, CFSTR("CFSocketCopyPeerAddress(): created socket %p peer address %@"), sock, result); return result; } @@ -446,11 +498,10 @@ CFOptionFlags CFSocketGetSocketFlags(CFSocketRef sock) { __block CFOptionFlags flags = 0; dispatch_sync(__sockQueue(), ^{ if (sock->_reenableRead) flags |= sock->_wantReadType; // flags are same as types here - if (sock->_reeanbleWrite) flags |= kCFSocketAutomaticallyReenableWriteCallBack; + if (sock->_reenableWrite) flags |= kCFSocketAutomaticallyReenableWriteCallBack; if (sock->_leaveErrors) flags |= kCFSocketLeaveErrors; if (sock->_closeOnInvalidate) flags |= kCFSocketCloseOnInvalidate; }); -// CFLog(5, CFSTR("CFSocketGetSocketFlags(%p): -> 0x%x"), sock, flags); return flags; } @@ -460,7 +511,7 @@ void CFSocketSetSocketFlags(CFSocketRef sock, CFOptionFlags flags) { __CFGenericValidateType(sock, CFSocketGetTypeID()); dispatch_sync(__sockQueue(), ^{ sock->_reenableRead = (sock->_wantReadType && ((flags & 0x3) == sock->_wantReadType)) ? true : false; - sock->_reeanbleWrite = (sock->_wantWrite && (flags & kCFSocketAutomaticallyReenableWriteCallBack)) ? true : false; + sock->_reenableWrite = (sock->_wantWrite && (flags & kCFSocketAutomaticallyReenableWriteCallBack)) ? true : false; sock->_leaveErrors = (flags & kCFSocketLeaveErrors) ? true : false; sock->_closeOnInvalidate = (flags & kCFSocketCloseOnInvalidate) ? true : false; if (sock->_shared) sock->_shared->_closeFD = sock->_closeOnInvalidate; @@ -475,21 +526,52 @@ void CFSocketEnableCallBacks(CFSocketRef sock, CFOptionFlags callBackTypes) { dispatch_sync(__sockQueue(), ^{ if (!__CFSocketIsValid(sock)) return; if (sock->_wantReadType && (callBackTypes & 0x3) == sock->_wantReadType) { - if (sock->_rsuspended && sock->_shared->_rdsrc) { + if (sockfd_is_readable(sock->_shared->_socket)) { + sock->_readable = true; +// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) socket is readable"), sock, callBackTypes); + if (!sock->_rsuspended) { + dispatch_suspend(sock->_shared->_rdsrc); + sock->_rsuspended = true; + } + if (sock->_shared->_source) { + CFRunLoopSourceSignal(sock->_shared->_source); + _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source); + } + } else if (sock->_rsuspended && sock->_shared->_rdsrc) { sock->_rsuspended = false; dispatch_resume(sock->_shared->_rdsrc); } sock->_readDisabled = false; } if (sock->_wantWrite && (callBackTypes & kCFSocketWriteCallBack)) { - if (sock->_wsuspended && sock->_shared->_wrsrc) { + if (sockfd_is_writeable(sock->_shared->_socket)) { + sock->_writeable = true; + if (!sock->_wsuspended) { + dispatch_suspend(sock->_shared->_wrsrc); + sock->_wsuspended = true; + } + if (sock->_shared->_source) { + CFRunLoopSourceSignal(sock->_shared->_source); + _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source); + } + } else if (sock->_wsuspended && sock->_shared->_wrsrc) { sock->_wsuspended = false; dispatch_resume(sock->_shared->_wrsrc); } sock->_writeDisabled = false; } if (sock->_wantConnect && !sock->_connected && (callBackTypes & kCFSocketConnectCallBack)) { - if (sock->_wsuspended && sock->_shared->_wrsrc) { + if (sockfd_is_writeable(sock->_shared->_socket)) { + sock->_writeable = true; + if (!sock->_wsuspended) { + dispatch_suspend(sock->_shared->_wrsrc); + sock->_wsuspended = true; + } + if (sock->_shared->_source) { + CFRunLoopSourceSignal(sock->_shared->_source); + _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source); + } + } else if (sock->_wsuspended && sock->_shared->_wrsrc) { sock->_wsuspended = false; dispatch_resume(sock->_shared->_wrsrc); } @@ -567,7 +649,14 @@ void CFSocketInvalidate(CFSocketRef sock) { sock->_shared->_source = NULL; sock->_shared->_refCnt--; if (0 == sock->_shared->_refCnt) { - if (sock->_shared->_closeFD) close(sock->_shared->_socket); + if (sock->_shared->_closeFD) { + // thoroughly stop anything else from using the fd + (void)shutdown(sock->_shared->_socket, SHUT_RDWR); + int nullfd = open("/dev/null", O_RDONLY); + dup2(nullfd, sock->_shared->_socket); + close(nullfd); + close(sock->_shared->_socket); + } free(sock->_shared); } sock->_shared = NULL; @@ -592,7 +681,14 @@ void CFSocketInvalidate(CFSocketRef sock) { Boolean CFSocketIsValid(CFSocketRef sock) { __CFGenericValidateType(sock, CFSocketGetTypeID()); - return __CFSocketIsValid(sock); + if (!__CFSocketIsValid(sock)) return false; + struct stat statbuf; + int ret = sock->_shared ? fstat(sock->_shared->_socket, &statbuf) : -1; + if (ret < 0) { + CFSocketInvalidate(sock); + return false; + } + return true; } @@ -604,27 +700,96 @@ static void __CFSocketPerform(void *info) { // CFRunLoop should only call this o __block Boolean doRead = false, doWrite = false, doConnect = false, isValid = false; __block int fd = INVALID_SOCKET; __block SInt32 errorCode = 0; + __block int new_fd = INVALID_SOCKET; + __block CFDataRef address = NULL; + __block CFMutableDataRef data = NULL; dispatch_sync(__sockQueue(), ^{ isValid = __CFSocketIsValid(sock); if (!isValid) return; + fd = sock->_shared->_socket; doRead = sock->_readable && sock->_wantReadType && !sock->_readDisabled; + if (doRead) { + sock->_readable = false; + doRead = sockfd_is_readable(fd); +// if (!doRead) CFLog(5, CFSTR("__CFSocketPerform(%p) socket is not actually readable"), sock); + } doWrite = sock->_writeable && sock->_wantWrite && !sock->_writeDisabled; doConnect = sock->_writeable && sock->_wantConnect && !sock->_connectDisabled && !sock->_connected; - if (doRead) sock->_readable = false; - if (doWrite || doConnect) sock->_writeable = false; - if (isValid) { - fd = sock->_shared->_socket; + if (doWrite || doConnect) { + sock->_writeable = false; + if (doWrite) doWrite = sockfd_is_writeable(fd); + if (doConnect) doConnect = sockfd_is_writeable(fd); } - if (isValid && !sock->_leaveErrors && (doWrite || doConnect)) { // not on read, for whatever reason + if (!sock->_leaveErrors && (doWrite || doConnect)) { // not on read, for whatever reason int errorSize = sizeof(errorCode); int ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&errorCode, (socklen_t *)&errorSize); if (0 != ret) errorCode = 0; sock->_error = errorCode; } sock->_connected = true; +// CFLog(5, CFSTR("__CFSocketPerform(%p) doing %d %d %d"), sock, doRead, doWrite, doConnect); + if (doRead) { + switch (sock->_wantReadType) { + case kCFSocketReadCallBack: + break; + case kCFSocketAcceptCallBack: { + uint8_t name[MAX_SOCKADDR_LEN]; + socklen_t namelen = sizeof(name); + new_fd = accept(fd, (struct sockaddr *)name, (socklen_t *)&namelen); + if (INVALID_SOCKET != new_fd) { + address = CFDataCreate(CFGetAllocator(sock), name, namelen); + } + break; + } + case kCFSocketDataCallBack: { + uint8_t name[MAX_SOCKADDR_LEN]; + socklen_t namelen = sizeof(name); + int avail = 0; + int ret = ioctl(fd, FIONREAD, &avail); + if (ret < 0 || avail < 256) avail = 256; + if ((1 << 20) < avail) avail = (1 << 20); + data = CFDataCreateMutable(CFGetAllocator(sock), 0); + CFDataSetLength(data, avail); + ssize_t len = recvfrom(fd, CFDataGetMutableBytePtr(data), avail, 0, (struct sockaddr *)name, (socklen_t *)&namelen); + CFIndex datalen = (len < 0) ? 0 : len; + CFDataSetLength(data, datalen); + if (0 < namelen) { + address = CFDataCreate(CFGetAllocator(sock), name, namelen); + } else if (sock->_connOriented) { + // cannot call CFSocketCopyPeerAddress(), or deadlock + if (!sock->_peerAddress) { + uint8_t name[MAX_SOCKADDR_LEN]; + socklen_t namelen = sizeof(name); + int ret = getpeername(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen); + if (0 == ret && 0 < namelen) { + sock->_peerAddress = CFDataCreate(CFGetAllocator(sock), name, namelen); + } + } + address = sock->_peerAddress ? (CFDataRef)CFRetain(sock->_peerAddress) : NULL; + } + if (NULL == address) { + address = CFDataCreate(CFGetAllocator(sock), NULL, 0); + } + break; + } + } + } + if (sock->_reenableRead) { +// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling read %d %p"), sock, sock->_rsuspended, sock->_shared->_rdsrc); + if (sock->_rsuspended && sock->_shared->_rdsrc) { + sock->_rsuspended = false; + dispatch_resume(sock->_shared->_rdsrc); + } + } + if (sock->_reenableWrite) { + if (sock->_wsuspended && sock->_shared->_wrsrc) { + sock->_wsuspended = false; + dispatch_resume(sock->_shared->_wrsrc); + } + } }); // CFLog(5, CFSTR("__CFSocketPerform(%p) isValid:%d, doRead:%d, doWrite:%d, doConnect:%d error:%d"), sock, isValid, doRead, doWrite, doConnect, errorCode); - if (!isValid) return; + if (!isValid || !(doConnect || doRead || doWrite)) return; void *context_info = NULL; void (*context_release)(const void *) = NULL; @@ -637,92 +802,41 @@ static void __CFSocketPerform(void *info) { // CFRunLoop should only call this o Boolean calledOut = false; if (doConnect) { -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing connect callback"), sock); if (sock->_callout) sock->_callout(sock, kCFSocketConnectCallBack, NULL, (0 != errorCode) ? &errorCode : NULL, context_info); -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing connect callback done"), sock); calledOut = true; } if (doRead && (!calledOut || __CFSocketIsValid(sock))) { switch (sock->_wantReadType) { case kCFSocketReadCallBack: -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing read callback"), sock); if (sock->_callout) sock->_callout(sock, kCFSocketReadCallBack, NULL, NULL, context_info); -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing read callback done"), sock); calledOut = true; break; - case kCFSocketAcceptCallBack: { - uint8_t name[MAX_SOCKADDR_LEN]; - int namelen = sizeof(name); - int new_fd = accept(fd, (struct sockaddr *)name, (socklen_t *)&namelen); + case kCFSocketAcceptCallBack: if (INVALID_SOCKET != new_fd) { - CFDataRef address = CFDataCreate(CFGetAllocator(sock), name, namelen); if (sock->_callout) sock->_callout(sock, kCFSocketAcceptCallBack, address, &new_fd, context_info); calledOut = true; - CFRelease(address); } break; - } - case kCFSocketDataCallBack: { - uint8_t name[MAX_SOCKADDR_LEN]; - int namelen = sizeof(name); - int avail = 0; - int ret = ioctl(fd, FIONREAD, &avail); - if (ret < 0 || avail < 256) avail = 256; - if ((1 << 20) < avail) avail = (1 << 20); - CFMutableDataRef data = CFDataCreateMutable(CFGetAllocator(sock), 0); - CFDataSetLength(data, avail); - ssize_t len = recvfrom(fd, CFDataGetMutableBytePtr(data), avail, 0, (struct sockaddr *)name, (socklen_t *)&namelen); - CFIndex datalen = (len < 0) ? 0 : len; - CFDataSetLength(data, datalen); - CFDataRef address = NULL; - if (0 < namelen) { - address = CFDataCreate(CFGetAllocator(sock), name, namelen); - } else if (sock->_connOriented) { - address = CFSocketCopyPeerAddress(sock); - } - if (NULL == address) { - address = CFDataCreate(CFGetAllocator(sock), NULL, 0); - } + case kCFSocketDataCallBack: if (sock->_callout) sock->_callout(sock, kCFSocketDataCallBack, address, data, context_info); calledOut = true; - if (0 == datalen) CFSocketInvalidate(sock); - if (address) CFRelease(address); - CFRelease(data); break; } - } } if (doWrite && (!calledOut || __CFSocketIsValid(sock))) { if (0 == errorCode) { -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing write callback"), sock); if (sock->_callout) sock->_callout(sock, kCFSocketWriteCallBack, NULL, NULL, context_info); -// CFLog(5, CFSTR("__CFSocketPerform(%p) doing write callback done"), sock); calledOut = true; } } -// CFLog(5, CFSTR("__CFSocketPerform(%p) callouts done"), sock); - - dispatch_sync(__sockQueue(), ^{ - if (!__CFSocketIsValid(sock)) return; - if (doRead && sock->_reenableRead) { -// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling read"), sock); - if (sock->_rsuspended && sock->_shared->_rdsrc) { - sock->_rsuspended = false; - dispatch_resume(sock->_shared->_rdsrc); - } - } - if (doWrite && sock->_reeanbleWrite) { -// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling write"), sock); - if (sock->_wsuspended && sock->_shared->_wrsrc) { - sock->_wsuspended = false; - dispatch_resume(sock->_shared->_wrsrc); - } - } - }); + if (data && 0 == CFDataGetLength(data)) CFSocketInvalidate(sock); + if (address) CFRelease(address); + if (data) CFRelease(data); if (context_release) { context_release(context_info); } + CHECK_FOR_FORK_RET(); // CFLog(5, CFSTR("__CFSocketPerform(%p) done"), sock); } @@ -746,9 +860,14 @@ static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) { CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef sock, CFIndex order) { CHECK_FOR_FORK_RET(NULL); __CFGenericValidateType(sock, CFSocketGetTypeID()); + if (!CFSocketIsValid(sock)) return NULL; __block CFRunLoopSourceRef result = NULL; dispatch_sync(__sockQueue(), ^{ if (!__CFSocketIsValid(sock)) return; + if (NULL != sock->_shared->_source && !CFRunLoopSourceIsValid(sock->_shared->_source)) { + CFRelease(sock->_shared->_source); + sock->_shared->_source = NULL; + } if (NULL == sock->_shared->_source) { CFRunLoopSourceContext context; context.version = 0; @@ -764,13 +883,33 @@ CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocke sock->_shared->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context); if (sock->_shared->_source) { if (sock->_wantReadType) { - if (sock->_rsuspended && sock->_shared->_rdsrc) { + if (sockfd_is_readable(sock->_shared->_socket)) { + sock->_readable = true; + if (!sock->_rsuspended) { + dispatch_suspend(sock->_shared->_rdsrc); + sock->_rsuspended = true; + } + if (sock->_shared->_source) { + CFRunLoopSourceSignal(sock->_shared->_source); + _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source); + } + } else if (sock->_rsuspended && sock->_shared->_rdsrc) { sock->_rsuspended = false; dispatch_resume(sock->_shared->_rdsrc); } } if (sock->_wantWrite || (sock->_wantConnect && !sock->_connected)) { - if (sock->_wsuspended && sock->_shared->_wrsrc) { + if (sockfd_is_writeable(sock->_shared->_socket)) { + sock->_writeable = true; + if (!sock->_wsuspended) { + dispatch_suspend(sock->_shared->_wrsrc); + sock->_wsuspended = true; + } + if (sock->_shared->_source) { + CFRunLoopSourceSignal(sock->_shared->_source); + _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source); + } + } else if (sock->_wsuspended && sock->_shared->_wrsrc) { sock->_wsuspended = false; dispatch_resume(sock->_shared->_wrsrc); } @@ -1042,24 +1181,45 @@ static SInt32 __CFSocketCreateWakeupSocketPair(void) { // Version 0 RunLoopSources set a mask in an FD set to control what socket activity we hear about. +// Changes to the master fs_sets occur via these 4 functions. CF_INLINE Boolean __CFSocketSetFDForRead(CFSocketRef s) { __CFReadSocketsTimeoutInvalid = true; - return __CFSocketFdSet(s->_socket, __CFReadSocketsFds); + Boolean b = __CFSocketFdSet(s->_socket, __CFReadSocketsFds); + if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) { + uint8_t c = 'r'; + send(__CFWakeupSocketPair[0], &c, sizeof(c), 0); + } + return b; } CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) { __CFReadSocketsTimeoutInvalid = true; - return __CFSocketFdClr(s->_socket, __CFReadSocketsFds); + Boolean b = __CFSocketFdClr(s->_socket, __CFReadSocketsFds); + if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) { + uint8_t c = 's'; + send(__CFWakeupSocketPair[0], &c, sizeof(c), 0); + } + return b; } CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) { // CFLog(5, CFSTR("__CFSocketSetFDForWrite(%p)"), s); - return __CFSocketFdSet(s->_socket, __CFWriteSocketsFds); + Boolean b = __CFSocketFdSet(s->_socket, __CFWriteSocketsFds); + if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) { + uint8_t c = 'w'; + send(__CFWakeupSocketPair[0], &c, sizeof(c), 0); + } + return b; } CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) { // CFLog(5, CFSTR("__CFSocketClearFDForWrite(%p)"), s); - return __CFSocketFdClr(s->_socket, __CFWriteSocketsFds); + Boolean b = __CFSocketFdClr(s->_socket, __CFWriteSocketsFds); + if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) { + uint8_t c = 'x'; + send(__CFWakeupSocketPair[0], &c, sizeof(c), 0); + } + return b; } @@ -1081,13 +1241,13 @@ static void __CFSocketInitializeSockets(void) { } } -static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) { +static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFRunLoopSourceRef src, CFMutableArrayRef runLoops) { CFRunLoopRef rl = NULL; - SInt32 idx, cnt = CFArrayGetCount(s->_runLoops); + SInt32 idx, cnt = CFArrayGetCount(runLoops); if (0 < cnt) { - rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, 0); + rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, 0); for (idx = 1; NULL != rl && idx < cnt; idx++) { - CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx); + CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx); if (value != rl) rl = NULL; } if (NULL == rl) { /* more than one different rl, so we must pick one */ @@ -1100,10 +1260,10 @@ static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) { Boolean foundIt = false, foundBackup = false; SInt32 foundIdx = 0; for (idx = 0; !foundIt && idx < cnt; idx++) { - CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx); + CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx); CFStringRef currentMode = CFRunLoopCopyCurrentMode(value); if (NULL != currentMode) { - if (CFRunLoopContainsSource(value, s->_source0, currentMode)) { + if (CFRunLoopContainsSource(value, src, currentMode)) { if (CFRunLoopIsWaiting(value)) { foundIdx = idx; foundIt = true; @@ -1115,10 +1275,10 @@ static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) { CFRelease(currentMode); } } - rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, foundIdx); + rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, foundIdx); CFRetain(rl); - CFArrayRemoveValueAtIndex(s->_runLoops, foundIdx); - CFArrayAppendValue(s->_runLoops, rl); + CFArrayRemoveValueAtIndex(runLoops, foundIdx); + CFArrayAppendValue(runLoops, rl); } else { CFRetain(rl); } @@ -1154,14 +1314,30 @@ static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) { if (callBackNow) { __CFSocketDoCallback(s, NULL, NULL, 0); } else { - CFRunLoopRef rl; CFRunLoopSourceSignal(s->_source0); - rl = __CFSocketCopyRunLoopToWakeUp(s); + CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops); + CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops); + CFRunLoopSourceRef source0 = s->_source0; + if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) { + source0 = NULL; + } + if (source0) CFRetain(source0); __CFSocketUnlock(s); + CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy); + if (source0) CFRelease(source0); if (NULL != rl) { CFRunLoopWakeUp(rl); CFRelease(rl); } + __CFSocketLock(s); + if (runLoopsOrig == s->_runLoops) { + s->_runLoops = runLoopsCopy; + runLoopsCopy = NULL; + CFRelease(runLoopsOrig); + } + __CFSocketUnlock(s); + CFRelease(runLoopsOrig); + if (runLoopsCopy) CFRelease(runLoopsCopy); } } @@ -1348,12 +1524,29 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) fprintf(stdout, "read signaling source for socket %d\n", s->_socket); #endif CFRunLoopSourceSignal(s->_source0); - CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(s); + CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops); + CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops); + CFRunLoopSourceRef source0 = s->_source0; + if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) { + source0 = NULL; + } + if (source0) CFRetain(source0); __CFSocketUnlock(s); + CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy); + if (source0) CFRelease(source0); if (NULL != rl) { CFRunLoopWakeUp(rl); CFRelease(rl); } + __CFSocketLock(s); + if (runLoopsOrig == s->_runLoops) { + s->_runLoops = runLoopsCopy; + runLoopsCopy = NULL; + CFRelease(runLoopsOrig); + } + __CFSocketUnlock(s); + CFRelease(runLoopsOrig); + if (runLoopsCopy) CFRelease(runLoopsCopy); } static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval* tv) @@ -1392,11 +1585,7 @@ void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, C /* activesocketslock protects our timeout calculation */ __CFSocketLock(s); __CFSpinLock(&__CFActiveSocketsLock); - -#if defined(LOG_CFSOCKET) - s->didLogSomething = false; -#endif - + if (s->_bytesToBuffer != length) { CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos; @@ -1604,7 +1793,8 @@ __attribute__ ((noreturn)) // mostly interesting for shutting up a warning #endif /* __GNUC__ */ static void __CFSocketManager(void * arg) { - if (objc_collectingEnabled()) auto_zone_register_thread(auto_zone()); + pthread_setname_np("com.apple.CFSocket.private"); + if (objc_collectingEnabled()) objc_registerThreadWithCollector(); SInt32 nrfds, maxnrfds, fdentries = 1; SInt32 rfds, wfds; fd_set *exceptfds = NULL; @@ -1650,13 +1840,13 @@ static void __CFSocketManager(void * arg) struct timeval* minTimeout = NULL; __CFReadSocketsTimeoutInvalid = false; #if defined(LOG_CFSOCKET) - fprintf(stdout, "Figuring out which sockets have timeouts...\n"); + fprintf(stdout, "Figuring out which sockets have timeouts...\n"); #endif CFArrayApplyFunction(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), _calcMinTimeout_locked, (void*) &minTimeout); if (minTimeout == NULL) { #if defined(LOG_CFSOCKET) - fprintf(stdout, "No one wants a timeout!\n"); + fprintf(stdout, "No one wants a timeout!\n"); #endif pTimeout = NULL; } else { @@ -1834,7 +2024,6 @@ static void __CFSocketManager(void * arg) } selectedReadSocketsIndex = 0; } - if (objc_collectingEnabled()) auto_zone_unregister_thread(auto_zone()); } static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) { @@ -1971,7 +2160,7 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN memory->_socketSetCount = 0; memory->_source0 = NULL; if (INVALID_SOCKET != sock) { - memory->_runLoops = CFArrayCreateMutable(allocator, 0, NULL); + memory->_runLoops = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL); } else { memory->_runLoops = NULL; } @@ -1992,6 +2181,7 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN memory->_leftoverBytes = NULL; if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory); + if (NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0); __CFSpinUnlock(&__CFAllSocketsLock); if (NULL != context) { void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info; @@ -2185,10 +2375,6 @@ void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) { __CFSpinUnlock(&__CFActiveSocketsLock); } __CFSocketUnlock(s); - if (wakeup && __CFSocketManagerThread) { - uint8_t c = 'u'; - send(__CFWakeupSocketPair[0], &c, sizeof(c), 0); - } } // "force" means to clear the disabled bits set by DisableCallBacks and always reenable. @@ -2244,12 +2430,10 @@ void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boole } if (__CFSocketSetFDForRead(s)) wakeup = true; } - if (wakeup && NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0); __CFSpinUnlock(&__CFActiveSocketsLock); } } __CFSocketUnlock(s); - if (wakeup) send(__CFWakeupSocketPair[0], &wakeupChar, sizeof(wakeupChar), 0); } void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) { @@ -2265,7 +2449,11 @@ static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) { __CFSocketLock(s); //??? also need to arrange delivery of all pending data if (__CFSocketIsValid(s)) { - CFArrayAppendValue(s->_runLoops, rl); + CFMutableArrayRef runLoopsOrig = s->_runLoops; + CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops); + CFArrayAppendValue(runLoopsCopy, rl); + s->_runLoops = runLoopsCopy; + CFRelease(runLoopsOrig); s->_socketSetCount++; // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it // is added to we just need to enable it there once (and _socketSetCount gives us a refCount @@ -2303,8 +2491,12 @@ static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) { __CFSpinUnlock(&__CFActiveSocketsLock); } if (NULL != s->_runLoops) { - idx = CFArrayGetFirstIndexOfValue(s->_runLoops, CFRangeMake(0, CFArrayGetCount(s->_runLoops)), rl); - if (0 <= idx) CFArrayRemoveValueAtIndex(s->_runLoops, idx); + CFMutableArrayRef runLoopsOrig = s->_runLoops; + CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops); + idx = CFArrayGetFirstIndexOfValue(runLoopsCopy, CFRangeMake(0, CFArrayGetCount(runLoopsCopy)), rl); + if (0 <= idx) CFArrayRemoveValueAtIndex(runLoopsCopy, idx); + s->_runLoops = runLoopsCopy; + CFRelease(runLoopsOrig); } __CFSocketUnlock(s); } @@ -2440,11 +2632,28 @@ static void __CFSocketPerformV0(void *info) { if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) { // if there's still more data, we want to wake back up right away if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) { - CFRunLoopSourceSignal(s->_source0); #if defined(LOG_CFSOCKET) fprintf(stdout, "perform short-circuit signaling source for socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected); #endif - rl = __CFSocketCopyRunLoopToWakeUp(s); + CFRunLoopSourceSignal(s->_source0); + CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops); + CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops); + CFRunLoopSourceRef source0 = s->_source0; + if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) { + source0 = NULL; + } + if (source0) CFRetain(source0); + __CFSocketUnlock(s); + rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy); + if (source0) CFRelease(source0); + __CFSocketLock(s); + if (runLoopsOrig == s->_runLoops) { + s->_runLoops = runLoopsCopy; + runLoopsCopy = NULL; + CFRelease(runLoopsOrig); + } + CFRelease(runLoopsOrig); + if (runLoopsCopy) CFRelease(runLoopsCopy); } } // Only reenable callbacks that are auto-reenabled @@ -2463,6 +2672,10 @@ CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocke __CFGenericValidateType(s, CFSocketGetTypeID()); __CFSocketLock(s); if (__CFSocketIsValid(s)) { + if (NULL != s->_source0 && !CFRunLoopSourceIsValid(s->_source0)) { + CFRelease(s->_source0); + s->_source0 = NULL; + } if (NULL == s->_source0) { CFRunLoopSourceContext context; context.version = 0; @@ -2580,11 +2793,11 @@ CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) { const uint8_t *name; SInt32 namelen, result = 0; __CFGenericValidateType(s, CFSocketGetTypeID()); - if (NULL == address) return -1; - if (!CFSocketIsValid(s)) return 0; + if (NULL == address) return kCFSocketError; + if (!CFSocketIsValid(s)) return kCFSocketError; name = CFDataGetBytePtr(address); namelen = CFDataGetLength(address); - if (!name || namelen <= 0) return 0; + if (!name || namelen <= 0) return kCFSocketError; CFSocketNativeHandle sock = CFSocketGetNative(s); result = bind(sock, (struct sockaddr *)name, namelen); if (0 == result) { @@ -2603,10 +2816,10 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI Boolean wasBlocking = true; __CFGenericValidateType(s, CFSocketGetTypeID()); - if (!CFSocketIsValid(s)) return 0; + if (!CFSocketIsValid(s)) return kCFSocketError; name = CFDataGetBytePtr(address); namelen = CFDataGetLength(address); - if (!name || namelen <= 0) return 0; + if (!name || namelen <= 0) return kCFSocketError; CFSocketNativeHandle sock = CFSocketGetNative(s); { SInt32 flags = fcntl(sock, F_GETFL, 0); diff --git a/CFTimeZone.c b/CFTimeZone.c index d976564..3e0a7bb 100644 --- a/CFTimeZone.c +++ b/CFTimeZone.c @@ -49,6 +49,7 @@ #else #error Unknown or unspecified DEPLOYMENT_TARGET #endif +#import #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED diff --git a/CFVersion.c b/CFVersion.c index 2ac3607..da4dfa8 100644 --- a/CFVersion.c +++ b/CFVersion.c @@ -21,9 +21,5 @@ * @APPLE_LICENSE_HEADER_END@ */ -/* CFVersion.c - Copyright 2009, Apple Inc. All rights reserved. - Responsibility: CFLite Team -*/ -const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-550.19 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; -double kCFCoreFoundationVersionNumber = (double)550.19; +const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-550 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; +double kCFCoreFoundationVersionNumber = (double)550; diff --git a/CFWindowsMessageQueue.c b/CFWindowsMessageQueue.c index 9b0ac8c..bd1502d 100644 --- a/CFWindowsMessageQueue.c +++ b/CFWindowsMessageQueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All rights reserved. + * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,6 +20,7 @@ * * @APPLE_LICENSE_HEADER_END@ */ + /* CFWindowsMessageQueue.c Copyright (c) 1999-2009, Apple Inc. All rights reserved. Responsibility: Christopher Kane diff --git a/CFWindowsMessageQueue.h b/CFWindowsMessageQueue.h index b7ac82f..bf094c9 100644 --- a/CFWindowsMessageQueue.h +++ b/CFWindowsMessageQueue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All rights reserved. + * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,6 +20,7 @@ * * @APPLE_LICENSE_HEADER_END@ */ + /* CFWindowsMessageQueue.h Copyright (c) 1999-2009, Apple Inc. All rights reserved. */ diff --git a/CoreFoundation.h b/CoreFoundation.h index 0ce50e1..943d037 100644 --- a/CoreFoundation.h +++ b/CoreFoundation.h @@ -92,15 +92,23 @@ #include +#if (TARGET_OS_MAC || TARGET_OS_WIN32) +#include +#endif + #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) +#include #include #endif - #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) #include #include #include #endif +#if TARGET_OS_WIN32 +#include +#include +#endif #endif /* ! __COREFOUNDATION_COREFOUNDATION__ */ diff --git a/Info.plist b/Info.plist index 3236f7d..a91b556 100644 --- a/Info.plist +++ b/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.6.1 + 6.6.4 CFBundleSignature ???? CFBundleVersion - 550.19 + 550.42 CarbonLazyValues CodeFragmentManager diff --git a/Makefile b/Makefile index 632a4d1..f3f4b7b 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ install: - DSTBASE="$(DSTROOT)/System/Library/Frameworks" ./BuildCFLite + DSTBASE="$(DSTROOT)/System/Library/Frameworks" ./BuildCFLite diff --git a/SymbolAliases b/SymbolAliases deleted file mode 100644 index 84b9421..0000000 --- a/SymbolAliases +++ /dev/null @@ -1,96 +0,0 @@ -_kCFCalendarIdentifierBuddhist _kCFBuddhistCalendar -_kCFCalendarIdentifierChinese _kCFChineseCalendar -_kCFCalendarIdentifierGregorian _kCFGregorianCalendar -_kCFCalendarIdentifierHebrew _kCFHebrewCalendar -_kCFCalendarIdentifierISO8601 _kCFISO8601Calendar -_kCFCalendarIdentifierIndian _kCFIndianCalendar -_kCFCalendarIdentifierIslamic _kCFIslamicCalendar -_kCFCalendarIdentifierIslamicCivil _kCFIslamicCivilCalendar -_kCFCalendarIdentifierJapanese _kCFJapaneseCalendar -_kCFCalendarIdentifierPersian _kCFPersianCalendar -_kCFCalendarIdentifierRepublicOfChina _kCFRepublicOfChinaCalendar - - -_kCFLocaleCalendarIdentifierKey _kCFLocaleCalendarIdentifier -_kCFLocaleCalendarKey _kCFLocaleCalendar -_kCFLocaleCollationIdentifierKey _kCFLocaleCollationIdentifier -_kCFLocaleCollatorIdentifierKey _kCFLocaleCollatorIdentifier -_kCFLocaleCountryCodeKey _kCFLocaleCountryCode -_kCFLocaleCurrencyCodeKey _kCFLocaleCurrencyCode -_kCFLocaleCurrencySymbolKey _kCFLocaleCurrencySymbol -_kCFLocaleDecimalSeparatorKey _kCFLocaleDecimalSeparator -_kCFLocaleExemplarCharacterSetKey _kCFLocaleExemplarCharacterSet -_kCFLocaleGroupingSeparatorKey _kCFLocaleGroupingSeparator -_kCFLocaleIdentifierKey _kCFLocaleIdentifier -_kCFLocaleLanguageCodeKey _kCFLocaleLanguageCode -_kCFLocaleMeasurementSystemKey _kCFLocaleMeasurementSystem -_kCFLocaleScriptCodeKey _kCFLocaleScriptCode -_kCFLocaleUsesMetricSystemKey _kCFLocaleUsesMetricSystem -_kCFLocaleVariantCodeKey _kCFLocaleVariantCode -_kCFDateFormatterAMSymbolKey _kCFDateFormatterAMSymbol -_kCFDateFormatterCalendarKey _kCFDateFormatterCalendar -_kCFDateFormatterCalendarIdentifierKey _kCFDateFormatterCalendarIdentifier -_kCFDateFormatterDefaultDateKey _kCFDateFormatterDefaultDate -_kCFDateFormatterDefaultFormatKey _kCFDateFormatterDefaultFormat -_kCFDateFormatterEraSymbolsKey _kCFDateFormatterEraSymbols -_kCFDateFormatterGregorianStartDateKey _kCFDateFormatterGregorianStartDate -_kCFDateFormatterIsLenientKey _kCFDateFormatterIsLenient -_kCFDateFormatterLongEraSymbolsKey _kCFDateFormatterLongEraSymbols -_kCFDateFormatterMonthSymbolsKey _kCFDateFormatterMonthSymbols -_kCFDateFormatterPMSymbolKey _kCFDateFormatterPMSymbol -_kCFDateFormatterQuarterSymbolsKey _kCFDateFormatterQuarterSymbols -_kCFDateFormatterShortMonthSymbolsKey _kCFDateFormatterShortMonthSymbols -_kCFDateFormatterShortQuarterSymbolsKey _kCFDateFormatterShortQuarterSymbols -_kCFDateFormatterShortStandaloneMonthSymbolsKey _kCFDateFormatterShortStandaloneMonthSymbols -_kCFDateFormatterShortStandaloneQuarterSymbolsKey _kCFDateFormatterShortStandaloneQuarterSymbols -_kCFDateFormatterShortStandaloneWeekdaySymbolsKey _kCFDateFormatterShortStandaloneWeekdaySymbols -_kCFDateFormatterShortWeekdaySymbolsKey _kCFDateFormatterShortWeekdaySymbols -_kCFDateFormatterStandaloneMonthSymbolsKey _kCFDateFormatterStandaloneMonthSymbols -_kCFDateFormatterStandaloneQuarterSymbolsKey _kCFDateFormatterStandaloneQuarterSymbols -_kCFDateFormatterStandaloneWeekdaySymbolsKey _kCFDateFormatterStandaloneWeekdaySymbols -_kCFDateFormatterTimeZoneKey _kCFDateFormatterTimeZone -_kCFDateFormatterTwoDigitStartDateKey _kCFDateFormatterTwoDigitStartDate -_kCFDateFormatterVeryShortMonthSymbolsKey _kCFDateFormatterVeryShortMonthSymbols -_kCFDateFormatterVeryShortStandaloneMonthSymbolsKey _kCFDateFormatterVeryShortStandaloneMonthSymbols -_kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey _kCFDateFormatterVeryShortStandaloneWeekdaySymbols -_kCFDateFormatterVeryShortWeekdaySymbolsKey _kCFDateFormatterVeryShortWeekdaySymbols -_kCFDateFormatterWeekdaySymbolsKey _kCFDateFormatterWeekdaySymbols -_kCFNumberFormatterAlwaysShowDecimalSeparatorKey _kCFNumberFormatterAlwaysShowDecimalSeparator -_kCFNumberFormatterCurrencyCodeKey _kCFNumberFormatterCurrencyCode -_kCFNumberFormatterCurrencyDecimalSeparatorKey _kCFNumberFormatterCurrencyDecimalSeparator -_kCFNumberFormatterCurrencyGroupingSeparatorKey _kCFNumberFormatterCurrencyGroupingSeparator -_kCFNumberFormatterCurrencySymbolKey _kCFNumberFormatterCurrencySymbol -_kCFNumberFormatterDecimalSeparatorKey _kCFNumberFormatterDecimalSeparator -_kCFNumberFormatterDefaultFormatKey _kCFNumberFormatterDefaultFormat -_kCFNumberFormatterExponentSymbolKey _kCFNumberFormatterExponentSymbol -_kCFNumberFormatterFormatWidthKey _kCFNumberFormatterFormatWidth -_kCFNumberFormatterGroupingSeparatorKey _kCFNumberFormatterGroupingSeparator -_kCFNumberFormatterGroupingSizeKey _kCFNumberFormatterGroupingSize -_kCFNumberFormatterInfinitySymbolKey _kCFNumberFormatterInfinitySymbol -_kCFNumberFormatterInternationalCurrencySymbolKey _kCFNumberFormatterInternationalCurrencySymbol -_kCFNumberFormatterIsLenientKey _kCFNumberFormatterIsLenient -_kCFNumberFormatterMaxFractionDigitsKey _kCFNumberFormatterMaxFractionDigits -_kCFNumberFormatterMaxIntegerDigitsKey _kCFNumberFormatterMaxIntegerDigits -_kCFNumberFormatterMaxSignificantDigitsKey _kCFNumberFormatterMaxSignificantDigits -_kCFNumberFormatterMinFractionDigitsKey _kCFNumberFormatterMinFractionDigits -_kCFNumberFormatterMinIntegerDigitsKey _kCFNumberFormatterMinIntegerDigits -_kCFNumberFormatterMinSignificantDigitsKey _kCFNumberFormatterMinSignificantDigits -_kCFNumberFormatterMinusSignKey _kCFNumberFormatterMinusSign -_kCFNumberFormatterMultiplierKey _kCFNumberFormatterMultiplier -_kCFNumberFormatterNaNSymbolKey _kCFNumberFormatterNaNSymbol -_kCFNumberFormatterNegativePrefixKey _kCFNumberFormatterNegativePrefix -_kCFNumberFormatterNegativeSuffixKey _kCFNumberFormatterNegativeSuffix -_kCFNumberFormatterPaddingCharacterKey _kCFNumberFormatterPaddingCharacter -_kCFNumberFormatterPaddingPositionKey _kCFNumberFormatterPaddingPosition -_kCFNumberFormatterPerMillSymbolKey _kCFNumberFormatterPerMillSymbol -_kCFNumberFormatterPercentSymbolKey _kCFNumberFormatterPercentSymbol -_kCFNumberFormatterPlusSignKey _kCFNumberFormatterPlusSign -_kCFNumberFormatterPositivePrefixKey _kCFNumberFormatterPositivePrefix -_kCFNumberFormatterPositiveSuffixKey _kCFNumberFormatterPositiveSuffix -_kCFNumberFormatterRoundingIncrementKey _kCFNumberFormatterRoundingIncrement -_kCFNumberFormatterRoundingModeKey _kCFNumberFormatterRoundingMode -_kCFNumberFormatterSecondaryGroupingSizeKey _kCFNumberFormatterSecondaryGroupingSize -_kCFNumberFormatterUseGroupingSeparatorKey _kCFNumberFormatterUseGroupingSeparator -_kCFNumberFormatterUseSignificantDigitsKey _kCFNumberFormatterUseSignificantDigits -_kCFNumberFormatterZeroSymbolKey _kCFNumberFormatterZeroSymbol -_kCFDateFormatterCalendarIdentifierKey _kCFDateFormatterCalendarName