5

I receive about 5,000 reported issue for reason "Received a notification with no notification name" everyday.

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException'  reason: 'Received a notification with no notification name'

Last Exception Backtrace:
0   CoreFoundation                      0x000000018206e950 __exceptionPreprocess + 132
1   libobjc.A.dylib                     0x000000018e5741fc objc_exception_throw + 60
2   CoreFoundation                      0x000000018206e810 +[NSException raise:format:arguments:] + 116
3   Foundation                          0x0000000182ba6db4 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 112
4   CoreTelephony                       0x00000001827ca39c -[CTTelephonyNetworkInfo handleNotificationFromConnection:ofType:withInfo:] + 272
5   CoreTelephony                       0x00000001827c9784 _ServerConnectionCallback(__CTServerConnection*, __CFString const*, __CFDictionary const*, void*) + 152
6   CoreTelephony                       0x00000001827de958 ___ZNK13CTServerState21sendNotification_syncE7CTEventPK10__CFStringPK14__CFDictionary_block_invoke15 + 32
7   libdispatch.dylib                   0x000000018eb4c014 _dispatch_call_block_and_release + 24
8   libdispatch.dylib                   0x000000018eb4bfd4 _dispatch_client_callout + 16
9   libdispatch.dylib                   0x000000018eb524a8 _dispatch_queue_drain + 640
10  libdispatch.dylib                   0x000000018eb4e4c0 _dispatch_queue_invoke + 68
11  libdispatch.dylib                   0x000000018eb530f4 _dispatch_root_queue_drain + 104
12  libdispatch.dylib                   0x000000018eb534fc _dispatch_worker_thread2 + 76
13  libsystem_pthread.dylib             0x000000018ece16bc _pthread_wqthread + 356
14  libsystem_pthread.dylib             0x000000018ece154c start_wqthread + 4

I found all CoreTelephony notification and tried to reproduce the issue but failed.

    /* For use with the CoreTelephony notification system. */
    extern CFStringRef kCTRegistrationStatusChangedNotification;
    extern CFStringRef kCTRegistrationStateDurationReportNotification;
    extern CFStringRef kCTRegistrationServiceProviderNameChangedNotification;
    extern CFStringRef kCTRegistrationOperatorNameChangedNotification;
    extern CFStringRef kCTRegistrationNewServingNetworkNotification;
    extern CFStringRef kCTRegistrationDataStatusChangedNotification;
    extern CFStringRef kCTRegistrationDataActivateFailedNotification;
    extern CFStringRef kCTRegistrationCellularDataPlanHideIndicatorNotification;
    extern CFStringRef kCTRegistrationCellularDataPlanActivateFailedNotification;
    extern CFStringRef kCTRegistrationCustomerServiceProfileUpdateNotification;
    extern CFStringRef kCTRegistrationCellChangedNotification;
    extern CFStringRef kCTRegistrationCauseCodeNotification;

Why do I get this crash?
And how can I change my code so that I do not get this issue anymore?
Any help is highly appreciated.

EDIT:

I am using Reachability class (https://github.com/tonymillion/Reachability) to detect network type.

+ (NSString *)networkName
 {    
    Reachability *reach = [Reachability reachabilityForInternetConnection];
    [reach startNotifier];

    NetworkStatus networkStatus = [reach currentReachabilityStatus];
    CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];

    if (networkStatus == ReachableViaWiFi) {
        return @"WIFI";
    } else if (networkStatus == ReachableViaWWAN) {
        if ([telephonyInfo respondsToSelector:@selector(currentRadioAccessTechnology)]) { 
            if ([[telephonyInfo currentRadioAccessTechnology] isEqualToString:CTRadioAccessTechnologyGPRS]) {
                return @"GPRS";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyEdge]) {
                return @"EDGE";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyWCDMA]) {
                return @"WCDMA";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyHSDPA]) {
                return @"HSDPA";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyHSUPA]) {
                return @"HSUPA";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
                return @"CDMA1X";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0]) {
                return @"CDMAEVDOREV0";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA]) {
                return @"CDMAEVDOREVA";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB]) {
                return @"CDMAEVDOREVB";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyeHRPD]) {
                return @"HRPD";
            } else if ([[telephonyInfo currentRadioAccessTechnology]  isEqualToString:CTRadioAccessTechnologyLTE]) {
                return @"LTE";
            }
            return @"UNKNOWN";
        } else {
            return @"WWAN";
        }
    } else {
        return @"NotReachable";
    }
}
JAL
  • 41,701
  • 23
  • 172
  • 300
Carina
  • 2,260
  • 2
  • 20
  • 45
  • Are you using CoreTelephony in your code at all, or do any of your dependencies use it? – JAL Jul 20 '16 at 13:35
  • Yes. I am using the `CTTelephonyNetworkInfo` class to respond to changes in the user’s cellular service provider. I have no idea with the notification with no notification name. @JAL – Carina Jul 20 '16 at 14:18
  • Can you add the CoreTelephony code used in your application to your question? It will be impossible to debug without it. – JAL Jul 20 '16 at 14:19
  • Thank you for reminding. @JAL – Carina Jul 20 '16 at 15:26

2 Answers2

1

I wonder if this is related to this similar issue with the old version of TestFlight:

There is an iOS bug that causes instances of the CTTelephonyNetworkInfo class to sometimes get notifications after they have been deallocated. Instead of instantiating, using, and releasing instances you must instead retain and never release them to work around the bug.

This smells like a zombie from the looks of your backtrace. Why not try using a static instance of CTTelephonyNetworkInfo that is never released as suggested in the linked question?

@import CoreTelephony;

// ...

static CTTelephonyNetworkInfo *netInfo;
static dispatch_once_t dispatchToken;
if (!netInfo) {
    dispatch_once(&dispatchToken, ^{
        netInfo = [[CTTelephonyNetworkInfo alloc] init];
    });
}
Community
  • 1
  • 1
JAL
  • 41,701
  • 23
  • 172
  • 300
  • Thanks. If it is caused by zombie, exception reason would be `SIGSEGV`(or `EXC_BAD_ACCESS`) , not `NSException` with reason "Received a notification with no notification name" . – Carina Jul 21 '16 at 03:08
  • @Carina Oh yeah that's a really good point. Ok, I'll investigate further. – JAL Jul 21 '16 at 03:17
1

To fix this issue, I use method swizzling to re-routing all calls that were originally sent to -[CTTelephonyNetworkInfo handleNotificationFromConnection:ofType:withInfo:] .
It works fine.

#import <CoreTelephony/CTTelephonyNetworkInfo.h>

struct __CTServerConnection {
    int a;
    int b;
    CFMachPortRef myport;
    int c;
    int d;
    int e;
    int f;
    int g;
    int h;
    int i;
};

typedef struct __CTServerConnection CTServerConnection;
typedef CTServerConnection* CTServerConnectionRef;


@implementation CTTelephonyNetworkInfo (Fixed)

- (void)fixed_handleNotificationFromConnection:(CTServerConnectionRef)connection
                                        ofType:(NSString *)notificationName
                                      withInfo:(NSDictionary *)info
{
    if ([notificationName length]) {
        return [self fixed_handleNotificationFromConnection:connection
                                                     ofType:notificationName
                                                   withInfo:info];
    }
}
Carina
  • 2,260
  • 2
  • 20
  • 45
  • Hi Carina, I'm interessted with your swizzling proposal. But I didn't succeeded in making this working. As I understand, handleNotificationFromConnection is a private API and this cannot be called since iOS 8.3. How did you make this working ? Many thanks – SlumTheSlug Aug 23 '16 at 13:13