2  * Copyright (c) 2000-2005, 2008-2015 Apple Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25  * Modification History 
  27  * June 1, 2001                 Allan Nathanson <ajn@apple.com> 
  28  * - public API conversion 
  30  * March 31, 2000               Allan Nathanson <ajn@apple.com> 
  34 #include <Availability.h> 
  35 #include <TargetConditionals.h> 
  36 #include <sys/cdefs.h> 
  37 #include <dispatch/dispatch.h> 
  38 #include <mach/mach.h> 
  39 #include <mach/mach_error.h> 
  41 #include <SystemConfiguration/SystemConfiguration.h> 
  42 #include <SystemConfiguration/SCPrivate.h> 
  43 #include "SCDynamicStoreInternal.h" 
  44 #include "config.h"             /* MiG generated file */ 
  46 #if !TARGET_IPHONE_SIMULATOR || (defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && (IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED >= 1090)) 
  47 #define HAVE_MACHPORT_GUARDS 
  52 notifyMPCopyDescription(const void *info
) 
  54         SCDynamicStoreRef       store   
= (SCDynamicStoreRef
)info
; 
  56         return CFStringCreateWithFormat(NULL
, 
  58                                         CFSTR("<SCDynamicStore notification MP> {store = %p}"), 
  64 rlsCallback(CFMachPortRef port
, void *msg
, CFIndex size
, void *info
) 
  66         os_activity_t                   activity_id
; 
  67         mach_no_senders_notification_t  
*buf            
= msg
; 
  68         mach_msg_id_t                   msgid           
= buf
->not_header
.msgh_id
; 
  69         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)info
; 
  70         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
  72         activity_id 
= os_activity_start("processing SCDynamicStore notification", 
  73                                         OS_ACTIVITY_FLAG_DEFAULT
); 
  75         if (msgid 
== MACH_NOTIFY_NO_SENDERS
) { 
  76                 /* the server died, disable additional callbacks */ 
  78                 SC_log(LOG_DEBUG
, "  notifier port closed"); 
  82                 if (port 
!= storePrivate
->rlsNotifyPort
) { 
  83                         SC_log(LOG_DEBUG
, "why is port != rlsNotifyPort?"); 
  87                 /* re-establish notification and inform the client */ 
  88                 (void)__SCDynamicStoreReconnectNotifications(store
); 
  92         SC_log(LOG_DEBUG
, "mach port callback, signal RLS"); 
  95         /* signal the real runloop source */ 
  96         if (storePrivate
->rls 
!= NULL
) { 
  97                 CFRunLoopSourceSignal(storePrivate
->rls
); 
 100         os_activity_end(activity_id
); 
 107 rlsSchedule(void *info
, CFRunLoopRef rl
, CFStringRef mode
) 
 109         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)info
; 
 110         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 113         SC_log(LOG_DEBUG
, "schedule notifications for mode %@", 
 114                (rl 
!= NULL
) ? mode 
: CFSTR("libdispatch")); 
 117         if (storePrivate
->rlList 
== NULL
) { 
 118                 CFMachPortContext       context         
= { 0 
 122                                                           , notifyMPCopyDescription
 
 125                 mach_port_t             oldNotify
; 
 126 #ifdef  HAVE_MACHPORT_GUARDS 
 127                 mach_port_options_t     opts
; 
 128 #endif  // HAVE_MACHPORT_GUARDS 
 133                 SC_log(LOG_DEBUG
, "  activate callback runloop source"); 
 136                 /* allocate a mach port for the SCDynamicStore notifications */ 
 140 #ifdef  HAVE_MACHPORT_GUARDS 
 141                 bzero(&opts
, sizeof(opts
)); 
 142                 opts
.flags 
= MPO_CONTEXT_AS_GUARD
|MPO_INSERT_SEND_RIGHT
; 
 144                 kr 
= mach_port_construct(mach_task_self(), &opts
, store
, &port
); 
 145 #else   // HAVE_MACHPORT_GUARDS 
 146                 kr 
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &port
); 
 147 #endif  // HAVE_MACHPORT_GUARDS 
 149                 if (kr 
!= KERN_SUCCESS
) { 
 150                         SC_log(LOG_NOTICE
, "could not allocate mach port: %s", mach_error_string(kr
)); 
 151                         if ((kr 
== KERN_NO_SPACE
) || (kr 
== KERN_RESOURCE_SHORTAGE
)) { 
 159 #ifndef HAVE_MACHPORT_GUARDS 
 160                 kr 
= mach_port_insert_right(mach_task_self(), 
 163                                             MACH_MSG_TYPE_MAKE_SEND
); 
 164                 if (kr 
!= KERN_SUCCESS
) { 
 166                          * We can't insert a send right into our own port!  This should 
 167                          * only happen if someone stomped on OUR port (so let's leave 
 170                         SC_log(LOG_NOTICE
, "mach_port_insert_right() failed: %s", mach_error_string(kr
)); 
 173 #endif  // HAVE_MACHPORT_GUARDS 
 175                 /* Request a notification when/if the server dies */ 
 176                 kr 
= mach_port_request_notification(mach_task_self(), 
 178                                                     MACH_NOTIFY_NO_SENDERS
, 
 181                                                     MACH_MSG_TYPE_MAKE_SEND_ONCE
, 
 183                 if (kr 
!= KERN_SUCCESS
) { 
 185                          * We can't request a notification for our own port!  This should 
 186                          * only happen if someone stomped on OUR port (so let's leave 
 189                         SC_log(LOG_NOTICE
, "mach_port_request_notification() failed: %s", mach_error_string(kr
)); 
 193                 if (oldNotify 
!= MACH_PORT_NULL
) { 
 194                         SC_log(LOG_NOTICE
, "oldNotify != MACH_PORT_NULL"); 
 199                 __MACH_PORT_DEBUG(TRUE
, "*** rlsSchedule", port
); 
 200                 kr 
= notifyviaport(storePrivate
->server
, port
, 0, (int *)&sc_status
); 
 202                 if (__SCDynamicStoreCheckRetryAndHandleError(store
, 
 205                                                              "rlsSchedule notifyviaport()")) { 
 209                 if (kr 
!= KERN_SUCCESS
) { 
 210                         if ((kr 
== MACH_SEND_INVALID_DEST
) || (kr 
== MIG_SERVER_DIED
)) { 
 211                                 /* remove the send right that we tried (but failed) to pass to the server */ 
 212                                 (void) mach_port_deallocate(mach_task_self(), port
); 
 215                         /* remove our receive right  */ 
 216 #ifdef  HAVE_MACHPORT_GUARDS 
 217                         (void) mach_port_destruct(mach_task_self(), port
, 0, store
); 
 218 #else   // HAVE_MACHPORT_GUARDS 
 219                         (void) mach_port_mod_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, -1); 
 220 #endif  // HAVE_MACHPORT_GUARDS 
 224                 if (sc_status 
!= kSCStatusOK
) { 
 225                         /* something [else] didn't work, remove our receive right  */ 
 226 #ifdef  HAVE_MACHPORT_GUARDS 
 227                         (void) mach_port_destruct(mach_task_self(), port
, 0, store
); 
 228 #else   // HAVE_MACHPORT_GUARDS 
 229                         (void) mach_port_mod_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, -1); 
 230 #endif  // HAVE_MACHPORT_GUARDS 
 234                 __MACH_PORT_DEBUG(TRUE
, "*** rlsSchedule (after notifyviaport)", port
); 
 235                 storePrivate
->rlsNotifyPort 
= _SC_CFMachPortCreateWithPort("SCDynamicStore", 
 239                 storePrivate
->rlsNotifyRLS 
= CFMachPortCreateRunLoopSource(NULL
, storePrivate
->rlsNotifyPort
, 0); 
 241                 storePrivate
->rlList 
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
); 
 244         if ((rl 
!= NULL
) && (storePrivate
->rlsNotifyRLS 
!= NULL
)) { 
 245                 if (!_SC_isScheduled(store
, rl
, mode
, storePrivate
->rlList
)) { 
 247                          * if we are not already scheduled with this runLoop / runLoopMode 
 249                         CFRunLoopAddSource(rl
, storePrivate
->rlsNotifyRLS
, mode
); 
 250                         __MACH_PORT_DEBUG(TRUE
, "*** rlsSchedule (after CFRunLoopAddSource)", CFMachPortGetPort(storePrivate
->rlsNotifyPort
)); 
 253                 _SC_schedule(store
, rl
, mode
, storePrivate
->rlList
); 
 261 rlsCancel(void *info
, CFRunLoopRef rl
, CFStringRef mode
) 
 264         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)info
; 
 265         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 268         SC_log(LOG_DEBUG
, "cancel notifications for mode %@", 
 269                (rl 
!= NULL
) ? mode 
: CFSTR("libdispatch")); 
 272         if ((rl 
!= NULL
) && (storePrivate
->rlsNotifyRLS 
!= NULL
)) { 
 273                 if (_SC_unschedule(store
, rl
, mode
, storePrivate
->rlList
, FALSE
)) { 
 275                          * if currently scheduled on this runLoop / runLoopMode 
 277                         n 
= CFArrayGetCount(storePrivate
->rlList
); 
 278                         if (n 
== 0 || !_SC_isScheduled(store
, rl
, mode
, storePrivate
->rlList
)) { 
 280                                  * if we are no longer scheduled to receive notifications for 
 281                                  * this runLoop / runLoopMode 
 283                                 CFRunLoopRemoveSource(rl
, storePrivate
->rlsNotifyRLS
, mode
); 
 293                 SC_log(LOG_DEBUG
, "  cancel callback runloop source"); 
 295                 __MACH_PORT_DEBUG((storePrivate
->rlsNotifyPort 
!= NULL
), 
 297                                   CFMachPortGetPort(storePrivate
->rlsNotifyPort
)); 
 299                 if (storePrivate
->rlList 
!= NULL
) { 
 300                         CFRelease(storePrivate
->rlList
); 
 301                         storePrivate
->rlList 
= NULL
; 
 304                 if (storePrivate
->rlsNotifyRLS 
!= NULL
) { 
 305                         /* invalidate & remove the run loop source */ 
 306                         CFRunLoopSourceInvalidate(storePrivate
->rlsNotifyRLS
); 
 307                         CFRelease(storePrivate
->rlsNotifyRLS
); 
 308                         storePrivate
->rlsNotifyRLS 
= NULL
; 
 311                 if (storePrivate
->rlsNotifyPort 
!= NULL
) { 
 314                         mp 
= CFMachPortGetPort(storePrivate
->rlsNotifyPort
); 
 315                         __MACH_PORT_DEBUG((storePrivate
->rlsNotifyPort 
!= NULL
), 
 316                                           "*** rlsCancel (before invalidating/releasing CFMachPort)", 
 319                         /* invalidate and release port */ 
 320                         CFMachPortInvalidate(storePrivate
->rlsNotifyPort
); 
 321                         CFRelease(storePrivate
->rlsNotifyPort
); 
 322                         storePrivate
->rlsNotifyPort 
= NULL
; 
 324                         /* and, finally, remove our receive right  */ 
 325 #ifdef  HAVE_MACHPORT_GUARDS 
 326                         (void) mach_port_destruct(mach_task_self(), mp
, 0, store
); 
 327 #else   // HAVE_MACHPORT_GUARDS 
 328                         (void) mach_port_mod_refs(mach_task_self(), mp
, MACH_PORT_RIGHT_RECEIVE
, -1); 
 329 #endif  // HAVE_MACHPORT_GUARDS 
 332                 if (storePrivate
->server 
!= MACH_PORT_NULL
) { 
 333                         kr 
= notifycancel(storePrivate
->server
, (int *)&sc_status
); 
 335                         (void) __SCDynamicStoreCheckRetryAndHandleError(store
, 
 338                                                                         "rlsCancel notifycancel()"); 
 340                         if (kr 
!= KERN_SUCCESS
) { 
 351 rlsPerform(void *info
) 
 353         os_activity_t                   activity_id
; 
 354         CFArrayRef                      changedKeys     
= NULL
; 
 356         void                            (*context_release
)(const void *); 
 357         SCDynamicStoreCallBack          rlsFunction
; 
 358         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)info
; 
 359         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 361         activity_id 
= os_activity_start("processing SCDynamicStore notification", 
 362                                         OS_ACTIVITY_FLAG_DEFAULT
); 
 365         SC_log(LOG_DEBUG
, "  executing notification function"); 
 368         changedKeys 
= SCDynamicStoreCopyNotifiedKeys(store
); 
 369         if (storePrivate
->disconnectForceCallBack
) { 
 370                 storePrivate
->disconnectForceCallBack 
= FALSE
; 
 371                 if (changedKeys 
== NULL
) { 
 372                         changedKeys 
= CFArrayCreate(NULL
, NULL
, 0, &kCFTypeArrayCallBacks
); 
 374         } else if ((changedKeys 
== NULL
) || (CFArrayGetCount(changedKeys
) == 0)) { 
 375                 /* if no changes or something happened to the server */ 
 379         rlsFunction 
= storePrivate
->rlsFunction
; 
 381         if (storePrivate
->rlsContext
.retain 
!= NULL
) { 
 382                 context_info    
= (void *)storePrivate
->rlsContext
.retain(storePrivate
->rlsContext
.info
); 
 383                 context_release 
= storePrivate
->rlsContext
.release
; 
 385                 context_info    
= storePrivate
->rlsContext
.info
; 
 386                 context_release 
= NULL
; 
 388         if (rlsFunction 
!= NULL
) { 
 389                 (*rlsFunction
)(store
, changedKeys
, context_info
); 
 391         if (context_release 
!= NULL
) { 
 392                 context_release(context_info
); 
 397         if (changedKeys 
!= NULL
) { 
 398                 CFRelease(changedKeys
); 
 401         os_activity_end(activity_id
); 
 408 rlsRetain(CFTypeRef cf
) 
 410         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)cf
; 
 411         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 413         switch (storePrivate
->notifyStatus
) { 
 414                 case NotifierNotRegistered 
: 
 415                         /* mark RLS active */ 
 416                         storePrivate
->notifyStatus 
= Using_NotifierInformViaRunLoop
; 
 417                         /* keep a reference to the store */ 
 420                 case Using_NotifierInformViaRunLoop 
: 
 423                         SC_log(LOG_NOTICE
, "unexpected notify status=%d", storePrivate
->notifyStatus
); 
 432 rlsRelease(CFTypeRef cf
) 
 434         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)cf
; 
 435         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 437         switch (storePrivate
->notifyStatus
) { 
 438                 case NotifierNotRegistered 
: 
 440                 case Using_NotifierInformViaRunLoop 
: 
 441                         /* mark RLS inactive */ 
 442                         storePrivate
->notifyStatus 
= NotifierNotRegistered
; 
 443                         storePrivate
->rls 
= NULL
; 
 445                         /* release our reference to the store */ 
 449                         SC_log(LOG_NOTICE
, "unexpected notify status=%d", storePrivate
->notifyStatus
); 
 458 rlsCopyDescription(const void *info
) 
 460         CFMutableStringRef              result
; 
 461         SCDynamicStoreRef               store           
= (SCDynamicStoreRef
)info
; 
 462         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 464         result 
= CFStringCreateMutable(NULL
, 0); 
 465         CFStringAppendFormat(result
, NULL
, CFSTR("<SCDynamicStore RLS> {")); 
 466         CFStringAppendFormat(result
, NULL
, CFSTR("store = %p"), store
); 
 467         if (storePrivate
->notifyStatus 
== Using_NotifierInformViaRunLoop
) { 
 468                 CFStringRef     description     
= NULL
; 
 470                 CFStringAppendFormat(result
, NULL
, CFSTR(", callout = %p"), storePrivate
->rlsFunction
); 
 472                 if ((storePrivate
->rlsContext
.info 
!= NULL
) && (storePrivate
->rlsContext
.copyDescription 
!= NULL
)) { 
 473                         description 
= (*storePrivate
->rlsContext
.copyDescription
)(storePrivate
->rlsContext
.info
); 
 475                 if (description 
== NULL
) { 
 476                         description 
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("<SCDynamicStore context %p>"), storePrivate
->rlsContext
.info
); 
 478                 if (description 
== NULL
) { 
 479                         description 
= CFRetain(CFSTR("<no description>")); 
 481                 CFStringAppendFormat(result
, NULL
, CFSTR(", context = %@"), description
); 
 482                 CFRelease(description
); 
 484         CFStringAppendFormat(result
, NULL
, CFSTR("}")); 
 491 SCDynamicStoreCreateRunLoopSource(CFAllocatorRef        allocator
, 
 492                                   SCDynamicStoreRef     store
, 
 495         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 498                 /* sorry, you must provide a session */ 
 499                 _SCErrorSet(kSCStatusNoStoreSession
); 
 503         if (storePrivate
->server 
== MACH_PORT_NULL
) { 
 504                 /* sorry, you must have an open session to play */ 
 505                 _SCErrorSet(kSCStatusNoStoreServer
); 
 509         switch (storePrivate
->notifyStatus
) { 
 510                 case NotifierNotRegistered 
: 
 511                 case Using_NotifierInformViaRunLoop 
: 
 512                         /* OK to enable runloop notification */ 
 515                         /* sorry, you can only have one notification registered at once */ 
 516                         _SCErrorSet(kSCStatusNotifierActive
); 
 520         if (storePrivate
->rls 
!= NULL
) { 
 521                 CFRetain(storePrivate
->rls
); 
 523                 CFRunLoopSourceContext  context 
= { 0                   // version 
 524                                                   , (void *)store       
// info 
 525                                                   , rlsRetain           
// retain 
 526                                                   , rlsRelease          
// release 
 527                                                   , rlsCopyDescription  
// copyDescription 
 530                                                   , rlsSchedule         
// schedule 
 531                                                   , rlsCancel           
// cancel 
 532                                                   , rlsPerform          
// perform 
 535                 storePrivate
->rls 
= CFRunLoopSourceCreate(allocator
, order
, &context
); 
 536                 if (storePrivate
->rls 
== NULL
) { 
 537                         _SCErrorSet(kSCStatusFailed
); 
 541         return storePrivate
->rls
; 
 546 SCDynamicStoreSetDispatchQueue(SCDynamicStoreRef store
, dispatch_queue_t queue
) 
 548         dispatch_group_t                drainGroup      
= NULL
; 
 549         dispatch_queue_t                drainQueue      
= NULL
; 
 550         dispatch_group_t                group           
= NULL
; 
 553         dispatch_source_t               source
; 
 554         SCDynamicStorePrivateRef        storePrivate    
= (SCDynamicStorePrivateRef
)store
; 
 557                 // sorry, you must provide a session 
 558                 _SCErrorSet(kSCStatusNoStoreSession
); 
 563                 if (storePrivate
->dispatchQueue 
== NULL
) { 
 564                         _SCErrorSet(kSCStatusInvalidArgument
); 
 572         if (storePrivate
->server 
== MACH_PORT_NULL
) { 
 573                 // sorry, you must have an open session to play 
 574                 _SCErrorSet(kSCStatusNoStoreServer
); 
 578         if ((storePrivate
->dispatchQueue 
!= NULL
) || (storePrivate
->rls 
!= NULL
)) { 
 579                 _SCErrorSet(kSCStatusInvalidArgument
); 
 583         if (storePrivate
->notifyStatus 
!= NotifierNotRegistered
) { 
 584                 // sorry, you can only have one notification registered at once... 
 585                 _SCErrorSet(kSCStatusNotifierActive
); 
 590          * mark our using of the SCDynamicStore notifications, create and schedule 
 591          * the notification port (storePrivate->rlsNotifyPort), and a bunch of other 
 594         storePrivate
->notifyStatus 
= Using_NotifierInformViaDispatch
; 
 595         rlsSchedule((void*)store
, NULL
, NULL
); 
 596         if (storePrivate
->rlsNotifyPort 
== NULL
) { 
 597                 /* if we could not schedule the notification */ 
 598                 _SCErrorSet(kSCStatusFailed
); 
 602         // retain the dispatch queue 
 603         storePrivate
->dispatchQueue 
= queue
; 
 604         dispatch_retain(storePrivate
->dispatchQueue
); 
 607         // We've taken a reference to the callers dispatch_queue and we 
 608         // want to hold on to that reference until we've processed any/all 
 609         // notifications.  To facilitate this we create a group, dispatch 
 610         // any notification blocks to via that group, and when the caller 
 611         // has told us to stop the notifications (unschedule) we wait for 
 612         // the group to empty and use the group's finalizer to release 
 613         // our reference to the SCDynamicStore. 
 615         group 
= dispatch_group_create(); 
 616         storePrivate
->dispatchGroup 
= group
; 
 618         dispatch_set_context(storePrivate
->dispatchGroup
, (void *)store
); 
 619         dispatch_set_finalizer_f(storePrivate
->dispatchGroup
, (dispatch_function_t
)CFRelease
); 
 621         // create a dispatch source for the mach notifications 
 622         mp 
= CFMachPortGetPort(storePrivate
->rlsNotifyPort
); 
 623         source 
= dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV
, mp
, 0, queue
); 
 624         if (source 
== NULL
) { 
 625                 SC_log(LOG_NOTICE
, "dispatch_source_create() failed"); 
 626                 _SCErrorSet(kSCStatusFailed
); 
 630         dispatch_source_set_event_handler(source
, ^{ 
 634                         u_int8_t                        buf
[sizeof(mach_msg_empty_t
) + MAX_TRAILER_SIZE
]; 
 635                         mach_msg_empty_rcv_t            msg
; 
 636                         mach_no_senders_notification_t  no_senders
; 
 639                 kr 
= mach_msg(¬ify_msg
.msg
.header
,   // msg 
 640                               MACH_RCV_MSG
,             // options 
 642                               sizeof(notify_msg
),       // rcv_size 
 644                               MACH_MSG_TIMEOUT_NONE
,    // timeout 
 645                               MACH_PORT_NULL
);          // notify 
 646                 if (kr 
!= KERN_SUCCESS
) { 
 647                         SC_log(LOG_NOTICE
, "mach_msg() failed, kr=0x%x", kr
); 
 651                 msgid 
= notify_msg
.msg
.header
.msgh_id
; 
 654                 dispatch_group_async(group
, queue
, ^{ 
 655                         if (msgid 
== MACH_NOTIFY_NO_SENDERS
) { 
 656                                 // re-establish notification and inform the client 
 657                                 (void)__SCDynamicStoreReconnectNotifications(store
); 
 659                         rlsPerform(storePrivate
); 
 664         dispatch_source_set_cancel_handler(source
, ^{ 
 665                 dispatch_release(source
); 
 668         storePrivate
->dispatchSource 
= source
; 
 669         dispatch_resume(source
); 
 677         if (storePrivate
->dispatchSource 
!= NULL
) { 
 678                 dispatch_source_cancel(storePrivate
->dispatchSource
); 
 679                 storePrivate
->dispatchSource 
= NULL
; 
 681         drainGroup 
= storePrivate
->dispatchGroup
; 
 682         storePrivate
->dispatchGroup 
= NULL
; 
 683         drainQueue 
= storePrivate
->dispatchQueue
; 
 684         storePrivate
->dispatchQueue 
= NULL
; 
 686         rlsCancel((void*)store
, NULL
, NULL
); 
 688         if (drainGroup 
!= NULL
) { 
 689                 dispatch_group_notify(drainGroup
, drainQueue
, ^{ 
 690                         // release group/queue references 
 691                         dispatch_release(drainQueue
); 
 692                         dispatch_release(drainGroup
);   // releases our store reference 
 696         storePrivate
->notifyStatus 
= NotifierNotRegistered
;