Application with SQLite3 db included crashing on Snow Leopard

Discussion in 'Mac Programming' started by Monaj, Jan 4, 2011.

  1. Monaj, Jan 4, 2011
    Last edited by a moderator: Jan 4, 2011

    Monaj macrumors regular

    Joined:
    May 24, 2009
    #1
    Hi all,

    I have included SQLite3 db within a cocoa application, from a Leopard system and saving and retrieving some data from it.

    Problem is - although it is running fine on Leopard, it is crashing on Snow Leopard.

    Part of the crash report is as follows:

    Code:
        Process:         RCS [84283]
        Path:            /Volumes/RCS Project/~RCS APPLICATIONS/~RCS (Macintosh)/2011/26-January 2011/RCS.app/Contents/MacOS/RCS
        Identifier:      com.tprf.RCS
        Version:         2.0 build-0235 (2.0)
        Code Type:       X86 (Native)
        Parent Process:  launchd [173]
        
        Date/Time:       2011-01-04 07:51:59.950 -0800
        OS Version:      Mac OS X 10.6.5 (10H574)
        Report Version:  6
        
        Interval Since Last Report:          494528 sec
        Crashes Since Last Report:           24
        Per-App Interval Since Last Report:  25 sec
        Per-App Crashes Since Last Report:   2
        Anonymous UUID:                       A9023F03-79EA-4444-B7BF-25AB6DD07985
        
        Exception Type:  EXC_BREAKPOINT (SIGTRAP)
        Exception Codes: 0x0000000000000002, 0x0000000000000000
        Crashed Thread:  0  Dispatch queue: com.apple.main-thread
        
        Application Specific Information:
        *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Failed to open database'
        *** Call stack at first throw:
        (
               0   CoreFoundation                      0x947e76ba __raiseError + 410
               1   libobjc.A.dylib                     0x9182e509 objc_exception_throw + 56
               2   CoreFoundation                      0x947e73e8 +[NSException raise:format:arguments:] + 136
               3   Foundation                          0x913e6bb3 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
               4   RCS                                 0x002af73c -[LocalDBController openDB] + 214
               5   RCS                                 0x00075157 -[SplashScreen awakeFromNib] + 32
               6   CoreFoundation                      0x9477f9b4 -[NSSet makeObjectsPerformSelector:] + 196
               7   AppKit                              0x94d2721c -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1566
               8   AppKit                              0x94d251f4 loadNib + 257
               9   AppKit                              0x94d245ed +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 228
               10  AppKit                              0x94d244fe +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 158
               11  AppKit                              0x94d24449 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 383
               12  AppKit                              0x94d2124d NSApplicationMain + 434
               13  RCS                                 0x00002ce6 start + 54
        )
        
        
        Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
        0   com.apple.CoreFoundation            0x94832a37 ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___ + 7
        1   libobjc.A.dylib                     0x9182e509 objc_exception_throw + 56
        2   com.apple.CoreFoundation            0x947e73e8 +[NSException raise:format:arguments:] + 136
        3   com.apple.Foundation                0x913e6bb3 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
        4   com.tprf.RCS                        0x002af73c -[LocalDBController openDB] + 214
        5   com.tprf.RCS                        0x00075157 -[SplashScreen awakeFromNib] + 32
        6   com.apple.CoreFoundation            0x9477f9b4 -[NSSet makeObjectsPerformSelector:] + 196
        7   com.apple.AppKit                    0x94d2721c -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1566
        8   com.apple.AppKit                    0x94d251f4 loadNib + 257
        9   com.apple.AppKit                    0x94d245ed +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 228
        10  com.apple.AppKit                    0x94d244fe +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 158
        11  com.apple.AppKit                    0x94d24449 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 383
        12  com.apple.AppKit                    0x94d2124d NSApplicationMain + 434
        13  com.tprf.RCS                        0x00002ce6 start + 54
    The method(s) which I call in beginning to initialize and open db are as follow:

    Code:
        -(void)dbInit{ // call in awake from NIB
            databaseName = [[NSString alloc] initWithString:@"test10.sql"];
        	
        	NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        	NSString *documentsDir = [documentPaths objectAtIndex:0];
        	databasePath = [[NSString alloc] initWithString:[documentsDir stringByAppendingPathComponent:databaseName]];
        	NSLog(@"databasePath - %@",databasePath);
        	
        	[self checkAndCreateDatabase];
        	
        }
        -(void)checkAndCreateDatabase{
        	BOOL success;
        	NSFileManager *fileManager = [NSFileManager defaultManager];
        	success = [fileManager fileExistsAtPath:databasePath];
        	NSLog(@"checkAndCreateDatabase, success - %d",success);
        	if(success){
        		[self openDB];
        		return;
        	}
        	NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
        	[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
        	[fileManager release];
        	
        	// opening db 
        	[self openDB];
        	
        }
        - (void)openDB{
        	if (sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK) 
        	{
        		sqlite3_close(database);
        		NSAssert(0, @"Failed to open database");
        	}
        	else{
        		NSLog(@"db successfully opened");
        	}
        }
    Can anyone suggest some solution for it?

    Thanks,

    Monaj
     
  2. ulbador, Jan 4, 2011
    Last edited: Jan 4, 2011

    ulbador macrumors 68000

    ulbador

    Joined:
    Feb 11, 2010
    #2
    Oh how this code looks familiar. I used that exact same tutorial when I was learning how to use SQLite on the iPhone. Something to do with animals if I remember...


    Have you checked before this line what "databasePath" actually is?

    Also, I think the reason you are getting this huge stack trace is because you are using NSAssert. The bottom line is that you KNOW that it failed at that point (you are effectively duplicating some logic at that point using the assert). You need to know WHY it failed to open the database.

    To be fair, I don't know if NSAssert forces it to print a whole stack trace by throwing an exception, so this is just conjecture, but it looks likely considering the error in the stack trace is the same as the error you "typed". For this usage, you are NOT getting any additional usable information by using NSAssert, and it may be confusing the problem more, considering the assert will "hit" every time because the 0 evaluates to false. With traditional C assert, I know this will terminate the program. Throwing an exception would effectively do the same thing to your program/



    Chances are, the path to the sqlite file isn't right, or the file itself isn't actually being deployed to the target. Finally, another option is that you didn't include the right SQLite framework. IIRC, there is SQLITE and SQLITE3 that you can include.
     
  3. Monaj, Jan 6, 2011
    Last edited: Jan 6, 2011

    Monaj thread starter macrumors regular

    Joined:
    May 24, 2009
    #3
    Solution found, but new doubts arise

    Hi all,

    To resolve the problem reported above, I tried to log the result returned from sqlite3_open. I got 14 ie. SQLITE_CANTOPEN. I checked permission for Documents and found that some permissions were not read & write. When I changed all to read & write, it started working properly :)

    Now there are some doubts :

    1. Is there any-other folder in which I should store SQLite3 db... other than documents.. should I store it in ~/Library/Application Support/ or any other folder?

    2. Can we check it via our code that- folder in which we are storing the db file has appropriate permissions or not?

    3. If folder does not have appropriate permission then can we change it via code?

    Can anyone clear these doubts or tell me the standard way to implement my requirements?

    Thanks,
    Monaj
     
  4. jiminaus, Jan 6, 2011
    Last edited: Jan 6, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    Is this conceptually a document to user? If it is, than you should provide the user with the ability to save the database whereever they want via a standard Save sheet.

    If this is not a document then it should not go in ~/Documents. ~/Documents should ONLY contain files explicitly saved there by the user. (Are you listening to this Microsoft and Adobe!?)

    If this is a database containing a cache of information that can be reconstructed if it is deleted or missing, then it should go in a subfolder of ~/Library/Caches.

    Otherwise putting the database in a subfolder of ~/Library/Application Support would be appropriate.

    NSFileManager has methods that can help here. Check out isWritableFileAtPath: and the like. The stat POSIX function should also work, if you're already familiar with that.

    NSFileManager has a setAttributes:ofItemAtPath:error: method which can change the POSIX permissions of a file. There's also a chmod POSIX function.

    Neither of these will be effective though if the file an Access Control Lists overriding the POSIX permissions. Search for acl in the developer documentation if want to tackle ACL's.
     

Share This Page