SocketStream::read crashes - ios

We use an in NSInputStream to receive data from an IMAP-server. We see a stange crash in Xcodes Crashes that we are not able to reproduce. The InputStream is initialized like this (i omitted some sanity-checks):
- (void)getStreamsToServer:(NSString *)hostName
andPort:(NSUInteger)port
andInputStream:(NSInputStream **)inputStream
andOutputStream:(NSOutputStream **)outputStream
{
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)(hostName),
(unsigned int)port,
&readStream,
&writeStream);
*inputStream = (__bridge_transfer NSInputStream *)readStream;
*outputStream = (__bridge_transfer NSOutputStream *)writeStream;
}
Later, we upgrade the streams to SSL:
[_inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[_outputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
And we try to read data from it like this:
NSUInteger READ_BUFFER_LENGTH = 16 * 1024;
uint8_t readBuffer[READ_BUFFER_LENGTH];
NSInteger readBytesCount = 0;
if([_inputStream hasBytesAvailable]) {
readBytesCount = [_inputStream read:readBuffer
maxLength:READ_BUFFER_LENGTH];
if (readBytesCount > 0) {
NSData *partialData = [NSData dataWithBytes:(const void *)readBuffer
length:readBytesCount];
}
This works in 99,99% of the time. But Xcodes crash reporter gives us some headache with this crash:
0 CoreFoundation 0x0000000184970620 CFHash + 360 (CFRuntime.c:1080)
1 CoreFoundation 0x00000001849718b8 CFBasicHashGetCountOfKey + 160 (CFBasicHash.c:455)
2 CoreFoundation 0x00000001849718b8 CFBasicHashGetCountOfKey + 160 (CFBasicHash.c:455)
3 CoreFoundation 0x0000000184971804 CFSetContainsValue + 208 (CFSet.c:405)
4 CoreFoundation 0x00000001849a0148 CFRunLoopRemoveSource + 164 (CFRunLoop.c:3542)
5 CFNetwork 0x0000000185113e78 SocketStream::read(__CFReadStream*, unsigned char*, long, CFStreamError*, unsigned char*) + 604 (SocketStream.cpp:2757)
6 CoreFoundation 0x000000018499c7c8 CFReadStreamRead + 480 (CFStream.c:1146)
This crash takes places in the line with [NSData dataWithBytes:length:].
Do you have any idea, how to provoke, debug or fix this error?

Try using SocketIO
socket.io-client-swift

Related

iOS crash using dispatch_sync

In my iOS app I read a large CSV file and load it (via inserts) in a SQLite database.
This is my code:
- (void) parseCSVFile:(NSString *)path
{
__block BOOL isFileOk = NO;
__block BOOL atLeastOneRowProcessed = NO;
NSFileManager *fileMgr = [[NSFileManager alloc] init];
unsigned long totalSize = [[[fileMgr attributesOfItemAtPath:path error:nil] objectForKey:#"NSFileSize"] intValue];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"mydatabase.sqlite"];
const char *dbpath = [writableDBPath UTF8String];
dispatch_queue_t databaseQueue = [(AppDelegate *)[[UIApplication sharedApplication] delegate] databaseQueue];
dispatch_sync(databaseQueue, ^{
sqlite3 *ddbb;
NSLog(#"INIT DATABASE");
if (sqlite3_open(dbpath, &ddbb) == SQLITE_OK)
{
char* errorMessage;
sqlite3_exec(ddbb, "DROP TABLE IF EXISTS datainfile", NULL, NULL, &errorMessage);
sqlite3_exec(ddbb, "CREATE TABLE \"datainfile\" (\"field1\" TEXT PRIMARY KEY NOT NULL ,\"field2\" TEXT DEFAULT (null) ,\"field3\" TEXT DEFAULT (null) ,\"field4\" TEXT)", NULL, NULL, &errorMessage);
sqlite3_exec(ddbb, "BEGIN TRANSACTION", NULL, NULL, &errorMessage);
char buffer[] = "INSERT OR IGNORE INTO datainfile VALUES (?1, ?2, ?3, ?4)";
sqlite3_stmt* stmt;
sqlite3_prepare_v2(ddbb, buffer, (int)strlen(buffer), &stmt, NULL);
char *pathUTF8 = (char*)[path UTF8String];
FILE* stream = fopen(pathUTF8, "r");
char *field1 = "";
char *field2 = "";
char *field3 = "";
char *field4 = "";
NSLog(#"READING FILE");
unsigned long processedSize = 0;
char line[1024];
while(fgets(line, 1024, stream))
{
processedSize = processedSize + strlen(line) * sizeof(char);
char* tmp = strdup(line);
field1 = strtok (tmp,", \t");
field2 = strtok (NULL, ", \t");
field3 = strtok (NULL, ", \t");
field4 = strtok (NULL, "\r\n");
atLeastOneRowProcessed = YES;
if(!isFileOk)
{
isFileOk = [self checkIfFileIsACorrectCSVWithField1:field1 field2:field2 field3:field3 andField4:field4];
if(!isFileOk)
{
if([_delegate respondsToSelector:#selector(fileParserError:)])
[_delegate fileParserError:_reportErrorMessage];
free(tmp);
break;
}
}
sqlite3_bind_text(stmt, 1, field1, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, field2, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, field3, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, field4, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE)
{
NSLog(#"ERROR: Commit Failed in line %s!\n", line);
// If there was an error we try to repeat the commit
sqlite3_reset(stmt);
sqlite3_bind_text(stmt, 1, field1, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, field2, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, field3, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, field4, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE)
{
NSLog(#"ERROR: Commit failed again");
}
else
{
NSLog(#"ERROR: Commit success");
}
}
sqlite3_reset(stmt);
free(tmp);
}
if(isFileOk)
{
NSLog(#"File read and now the commit starts");
sqlite3_exec(ddbb, "COMMIT TRANSACTION", NULL, NULL, &errorMessage);
_phase = PARSER_PHASE_CREATING_INDEX;
sqlite3_exec(ddbb, "CREATE INDEX field1 ON datainfile(field1);", NULL, NULL, &errorMessage);
sqlite3_finalize(stmt);
NSLog(#"Commit has ended");
}
}
sqlite3_close(ddbb);
});
if(isFileOk)
{
if([_delegate respondsToSelector:#selector(fileParserFinished)])
[_delegate fileParserFinished];
}
else
{
if(!atLeastOneRowProcessed)
{
_reportErrorMessage = NSLocalizedString(#"TXT_FILEERROR_NOPROCESSED", Nil);
if([_delegate respondsToSelector:#selector(fileParserError:)])
[_delegate fileParserError:_reportErrorMessage];
}
}
}
databaseQueue is an attribute of AppDelegate created this way:
_databaseQueue = dispatch_queue_create("com.mycompany.myapp.database", 0);
Well, this is working well almost always. But sometimes it happens a strange crash. This is the log:
Crashed: com.mycompany.myapp.database
0 libsystem_kernel.dylib 0x1865d1014 __pthread_kill + 8
1 libsystem_pthread.dylib 0x18669b264 pthread_kill + 112
2 libsystem_c.dylib 0x1865459c4 abort + 140
3 libsystem_c.dylib 0x186545ad8 _UTF2_init + 82
4 libsystem_c.dylib 0x186559c7c __chk_fail_overlap + 54
5 libsystem_c.dylib 0x186559c44 __chk_fail + 18
6 libsystem_c.dylib 0x18655a04c __vsprintf_chk + 134
7 MyApp 0x1000c151c __32-[FileParser parseCSVFile:]_block_invoke (FileParser.m:650)
8 libdispatch.dylib 0x18648e9a0 _dispatch_client_callout + 16
9 libdispatch.dylib 0x18649bee0 _dispatch_barrier_sync_f_invoke + 84
10 MyApp 0x1000c1084 -[FileParser parseCSVFile:] (FileParser.m:734)
11 MyApp 0x1000bed28 -[FileParser readFileWithPath:andDelegate:] (FileParser.m:147)
12 MyApp 0x100041a64 __57-[HomeViewController readFileWithPath:]_block_invoke_2 (HomeViewController.m:625)
13 libdispatch.dylib 0x18648e9e0 _dispatch_call_block_and_release + 24
14 libdispatch.dylib 0x18648e9a0 _dispatch_client_callout + 16
15 libdispatch.dylib 0x18649d0d4 _dispatch_queue_override_invoke + 644
16 libdispatch.dylib 0x18649ea50 _dispatch_root_queue_drain + 540
17 libdispatch.dylib 0x18649e7d0 _dispatch_worker_thread3 + 124
18 libsystem_pthread.dylib 0x186697100 _pthread_wqthread + 1096
19 libsystem_pthread.dylib 0x186696cac start_wqthread + 4
It happens in the lines 734 and 650 of my FileParser, and these lines are:
(line 734) the second if(isFileOk)
Just the first line after leaving the dispatch_sync.
(line 650) processedSize = processedSize + strlen(line) * sizeof(char);
Reading the first line of the CSV file.
It seems to me like the dispatch_sync leaves its code before it's executed, calling "simultaneously" a line outside the block and one line inside the block.
I must add that when this crash has happened the line that crashed outside the block is always if(isFileOk), but the line that crashed inside the block varies.
What could it be happening?

Crash while using CFHostCreateWithName: "Attempt to start the Thread again"

help!
I met a crash when i try to get the addresses for the give hostname;
the crash log shows like this:
1 libobjc.A.dylib 0x0000000197d180e4 objc_exception_throw + 56
2 CoreFoundation 0x0000000186044218 -[NSException initWithCoder:]
3 Foundation 0x0000000186e9528c -[NSThread start] + 136
4 ZFirewall7.dylib 0x0000000105e4d768 -[FiPSettingsManager doHostStuff:] + 1124
5 ZFirewall7.dylib 0x0000000105e48424 _ZL23my_CFHostCreateWithNamePPK13__CFAllocatorPPK10__CFString + 164
6 Upload 0x000000010220d1c0 +[UploadUtil addressesForHostname:] (UploadUtil.m:277)
7 Upload 0x000000010220d120 +[UploadUtil addressForHostname:] (UploadUtil.m:267)
....
*** -[NSThread start]: attempt to start the thread again
and my code is:
+(NSArray *)addressesForHostname:(NSString *)hostname
{
// Get the addresses for the given hostname.
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)hostname);
BOOL isSuccess = CFHostStartInfoResolution(hostRef, kCFHostAddresses, nil);
if (!isSuccess)
{
CFRelease(hostRef);
return nil;
}
CFArrayRef addressesRef = CFHostGetAddressing(hostRef, nil);
if (addressesRef == nil)
{
CFRelease(hostRef);
return nil;
}
// Convert these addresses into strings.
char ipAddress[INET6_ADDRSTRLEN];
NSMutableArray *addresses = [NSMutableArray array];
CFIndex numAddresses = CFArrayGetCount(addressesRef);
for (CFIndex currentIndex = 0; currentIndex < numAddresses; currentIndex++) {
struct sockaddr *address = (struct sockaddr *)CFDataGetBytePtr(CFArrayGetValueAtIndex(addressesRef, currentIndex));
if (address == nil)
{
CFRelease(hostRef);
return nil;
}
getnameinfo(address, address->sa_len, ipAddress, INET6_ADDRSTRLEN, nil, 0, NI_NUMERICHOST);
[addresses addObject:[NSString stringWithCString:ipAddress encoding:NSASCIIStringEncoding]];
}
CFRelease(hostRef);
return addresses;
}
this function do called by several threads, and the doc of CFHostCreateWithName says that it is thread safe, now i have no idea about how to solve this problem.
help!

Getting IPV4 address as a String

Im using Bonjour to browse for available services from specific devices. I can successfully obtain and resolve the services returned from the browse, however I would like to take the service and retrieve it's IPV4 address in String form. To do this I am using the arpa/inet library to translate the NSdata object received by the NSNetService.addresses into a String. The code below works most of the time however occasionally the line below results in the crashing of the app.
NSString *ipString = [NSString stringWithFormat: #"%s",
inet_ntoa(socketAddress->sin_addr)];
The error: EXC_BAD_ACCESS
I am sure it has to do with the way I have declared this code, any ideas?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
Stack trace:
2015-08-13 08:23:45.860 Semiphores[4664:2119558] Stack trace : (
0 Semiphores 0x0000000100001c0b +[BonjourAddressHelper getStringFromAddressData:] + 107
1 Semiphores 0x0000000100007c8a _TFFC10Semiphores17BonjourController15resolveServicesFS0_FPSs9AnyObject_T_U_FT_T_ + 2682
2 Semiphores 0x0000000100007207 _TTRXFo__dT__XFdCb__dT__ + 39
3 libdispatch.dylib 0x00000001006852bb _dispatch_call_block_and_release + 12
4 libdispatch.dylib 0x000000010067fd43 _dispatch_client_callout + 8
5 libdispatch.dylib 0x0000000100683283 _dispatch_root_queue_drain + 1471
6 libdispatch.dylib 0x0000000100694cd0 _dispatch_worker_thread3 + 106
7 libsystem_pthread.dylib 0x00007fff86770637 _pthread_wqthread + 729
8 libsystem_pthread.dylib 0x00007fff8676e40d start_wqthread + 13
)
What would happen if someone passed in nil data?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
if (dataIn != nil) {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
return #"";
}

Getting CocoaLibSpotify error in SPPlaylist.m

When I try to build my project i get the following error on line 827
/PATH_TO_PROJECT/Libs/CocoaLibSpotify/Model/SPPlaylist.m:827:25: Implicit conversion of Objective-C pointer type 'AVAssetTrack *' to C pointer type 'sp_track *' (aka 'struct sp_track *') requires a bridged cast
Here is the code where the error occurs:
805 -(void)addItems:(NSArray *)newItems atIndex:(NSUInteger)index callback:(SPErrorableOperationCallback)block {
806
807 SPDispatchAsync(^{
808
809 if (newItems.count == 0) {
810 dispatch_async(dispatch_get_main_queue(), ^{
811 if (block) block([NSError spotifyErrorWithCode:SP_ERROR_INVALID_INDATA]);
812 });
813 return;
814 }
815
816 sp_track **tracks = malloc(sizeof(sp_track *) * newItems.count);
817
818 // libSpotify iterates through the array and inserts each track at the given index,
819 // which ends up reversing the expected order. Defeat this by constructing a backwards
820 // array.
821 for (int currentTrack = (int)newItems.count - 1; currentTrack >= 0; currentTrack--) {
822
823 sp_track *track;
824 id item = [newItems objectAtIndex:currentTrack];
825
826 if ([item isKindOfClass:[SPTrack class]])
827 track = [item track];
828 else
829 track = [(SPTrack *)((SPPlaylistItem *)item).item track];
830
831 tracks[currentTrack] = track;
832 }
833 sp_track *const *trackPointer = tracks;
834
835 if (block)
836 [self.addCallbackStack addObject:block];
837
838 sp_error errorCode = sp_playlist_add_tracks(self.playlist, trackPointer, (int)newItems.count, (int)index, self.session.session);
839 free(tracks);
840 tracks = NULL;
841
842 NSError *error = nil;
843 if (errorCode != SP_ERROR_OK)
844 error = [NSError spotifyErrorWithCode:errorCode];
845
846 if (error && block) {
847 [self.addCallbackStack removeObject:block];
848 dispatch_async(dispatch_get_main_queue(), ^{ block(error); });
849 }
850 });
851 }
Thanks for your help!
The error is pretty self-explanatory - you need to make a bridged cast.
track = (__bridge sp_track *)[item track];
or
track = [(SPPlaylistItem *)item track];

Crash EXC_BAD_ACCESS on string with format

I am processing raw IP data to process a video signal (ATSC-MH). However, I am having issues with some basic issue and I'm apparently fried at the moment and need another set of eyes.
This is the function that flips. Funny part is that it was working for a while and I can't rememeber what I changes. The line that is **d is the one that is referred to in the error log. I can't do much NSLog debugging because the stream comes from an accessory(so no direct debugging pipe :().
-(NSString*)reportSMT{
//NSString* ret = #"Not implemented yet";
__autoreleasing NSMutableString* ret = [[NSMutableString alloc] initWithFormat:#"\nSMT:\n SecSynInd:%# PriInd:%#\n SecLen:%d SMTMHProVer:%d\n EnID:%d VerNum:%d\n CurNxtInd:%# SecNum:%d\n lastSec#:%d #Servs:%d\n\n",(Header.section_syntax_indicator?#"YES":#"NO"),(Header.private_indicator?#"YES":#"NO"),Header.section_length,Header.SMT_MH_protocol_version,Header.ensemble_id,Header.version_number,(Header.current_next_indicator?#"YES":#"NO"), Header.section_number,Header.last_section_number,Header.num_MH_services];
[ret appendString:[NSString stringWithFormat:#"SMT Table:\n"]];
for (int i = 0; i<Header.num_MH_services; i++) {
**[ret appendString:[NSString stringWithFormat:#"Serv(%d):\n ServID:%d MultiEnServ:%d\n ServStat:%d ServSPInd:%#\n ServShotName:%#\n ServCat:%d\n source:%# dest:%#\n #MHServComps:%d\n",i,Services[i].MH_service_id,Services[i].multi_ensemble_service,Services[i].MH_service_status,(Services[i].SP_indicator?#"YES":#"NO"),[NSString stringWithUTF8String:(char*)Services[i].short_MH_service_name],(Services[i].service_source_IP_address_flag?[Utility ParseIP:Services[i].service_source_IP_address]:#"N/A"),(Services[i].service_destination_IP_address_flag?[Utility ParseIP:Services[i].service_destination_IP_address]:#"N/A"),Services[i].num_components]];**
for (int m=0; m<Services[i].num_components; m++) {
[ret appendString:[NSString stringWithFormat:#" Comp(%d)(essential:%#):\n port#count:%d compSource:%#\n compDest:%# destPort:%d\n",m,(Services[i].components[m].essential_component_indicator?#"YES":#"NO") ,Services[i].components[m].port_num_count,(Services[i].components[m].component_source_IP_address_flag?[Utility ParseIP:Services[i].components[m].component_source_IP_address]:#"N/A"),(Services[i].components[m].component_destination_IP_address_flag?[Utility ParseIP:Services[i].components[m].component_destination_IP_address]:#"N/A"),Services[i].components[m].component_destination_UDP_port_num]];
}
}
return [ret copy];
}
Here is that Utility parseIP function. Though it didn't change anything to comment the call to it and hardcode a value there:
+(NSString*)ParseIP:(long)ip{
__autoreleasing NSString* ret = nil;
if (ip) {
unsigned char* ipPtr = (unsigned char*)&ip;
unsigned char ipc[4];
for (int i=0; i<4; i++) {
ipc[i] = *(ipPtr+i);
}
ret = [NSString stringWithFormat:#"(%d.%d.%d.%d)",ipc[3],ipc[2],ipc[1],ipc[0]];
}
return ret;
}
Here is the structure for that part of the SMT:
struct SMTChunk{
unsigned int MH_service_id;//16
unsigned char multi_ensemble_service;//2
unsigned char MH_service_status;//2
bool SP_indicator;//1
unsigned char short_MH_service_name_length;//3 /* m */
unsigned char* short_MH_service_name;//16*m
unsigned char reserved2;//2 should be 11
unsigned char MH_service_category;//6
unsigned char num_components;//5
bool IP_version_flag;//1
bool service_source_IP_address_flag;//1
bool service_destination_IP_address_flag;//1
unsigned long service_source_IP_address;//32 if (service_source_IP_address_flag)
unsigned long service_destination_IP_address;//32 if (service_destination _IP_address_flag)
struct SMTComponent* components;
unsigned char reserved4;//4 1111(f)
unsigned char num_MH_service_level_descriptors;//4
struct SMTServiceDescriptor* descriptors;
};
Like I said this was working before, so I'm pretty sure the parser that fills the data structure is fine.
Device Log(important part):
Date/Time: 2012-03-06 00:56:40.480 -0600
OS Version: iPhone OS 5.0.1 (9A405)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000a
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x300e4fb6 objc_msgSend + 10
1 Foundation 0x30dd9d14 _NSDescriptionWithLocaleFunc + 44
2 CoreFoundation 0x335d699e __CFStringAppendFormatCore + 7998
3 CoreFoundation 0x33551210 _CFStringCreateWithFormatAndArgumentsAux + 68
4 Foundation 0x30dd9c3e +[NSString stringWithFormat:] + 54
5 APT-test 0x000c9630 -[SMT reportSMT] (SMT.m:178)
6 APT-test 0x000c54bc -[VideoViewController saveTimerFun:] (VideoViewController.mm:940)
7 Foundation 0x30e79616 __NSFireTimer + 138
It feels like I've been working on this app forever so any help or pointers you can give are welcome.
Thanks in advance!
The printf wildcards and arguments do not appear to be balanced properly:
[NSString stringWithFormat:#"1%d 2%d 3%d 4%d 5%# 6%# 7%d 8%# 9%# A%d",
/* 1 */i,
/* 2 */Services[i].MH_service_id,
/* 3 */Services[i].multi_ensemble_service,
/* 4 */Services[i].MH_service_status,
/* 5 */(Services[i].SP_indicator?#"YES":#"NO"),
/* 6 */[NSString stringWithUTF8String:(char*)Services[i].short_MH_service_name],
/* 7 */(Services[i].service_source_IP_address_flag?[Utility ParseIP:Services[i].service_source_IP_address]:#"N/A"),
/* 8 */(Services[i].service_destination_IP_address_flag?[Utility ParseIP:Services[i].service_destination_IP_address]:#"N/A"),
/* 9 */Services[i].num_components]];
It looks like you’re trying to match the %# specifier at position 9 with Services[i].num_components, which is quite probable to result in EXC_BAD_ACCESS. You would do best to rewrite the code so that it’s more readable, this mess is only asking for trouble.

Resources