fmdbqueue dealock可能的一个原因

症状表现:

    总是crash ,后台打印:

     inDatabase: was called reentrantly on the same queue, which would lead to a deadlock

    错误代码如下:


     

  //use fmdb larger bugs ,不能在执行一个fmdbqueue还没有执行完毕的时候,去执行另外一个fmdbqueue


    [[SQLUtils getInstance]saveRulesAction:rulesArray rulesDescription:ruleDescription result:^(BOOL sucess) {


      [[SQLUtils getInstance]updateRules];

        if(done){

            done(sucess);

            //the rule has changed we should check it now

            if(sucess){

                dispatch_async(dispatch_get_main_queue(), ^{

                    [self checkRules];

                });

            }

        }

    }];


-(void)saveRulesAction:(NSArray*)rules rulesInfo:(NSArray*)ruleInfo rulesDescription:(NSArray*)rulesDescription result:(void(^)(BOOL sucess))done

{

    [self checkDBQueue];

    __block BOOL is_exculate_success = NO;

    [queue inDatabase:^(FMDatabase *db) {

        [db beginTransaction];

        @try{


            for(int i=0;i<[ruleInfo count];i++){

                //delete the rules in db

                BOOL rc = [db executeUpdate:@"delete from rulesAction where ruleType=?",ruleInfo[i]];

                if(!rc){

                    debugLog(@"table rulesAction delete info error! info:%@",[db lastErrorMessage]);

                }

            }

            //ruleType actionType TEXT NOT NULL)"];

            //delete rules description info

            BOOL rc  = [db executeUpdate:@"delete from rulesDescription"];

            if(!rc){

                debugLog(@"table rulesDescription delete info error! info:%@",[db lastErrorMessage]);

            }

            

            if(rulesDescription!=nil){

                //save rules description info

                rc= [db executeUpdate:@"insert into rulesDescription(uuid,displayName,description) values (?,?,?)",rulesDescription[0],rulesDescription[1],rulesDescription[2]];

            }else{

                // rules description is nill

                //debugLog(@"rules description is nil");

            }


            //save all rules and action

            for (int i =0; i<[rules count]; i++) {

                NSArray * rule = rules[i];

                BOOL rc = [db executeUpdate:@"insert into rulesAction(ruleType,actionType,time,actionIndex,ruleLevel,hasDone,rulesKey,ruleTime) values (?,?,?,?,?,?,?,datetime('now'))",rule[0],rule[1],rule[2],rule[3],rule[4],rule[5],rule[6]];

                if(!rc){

                    debugLog(@"saveRulesAction into db failed!  db error info is %@",[currentDB lastErrorMessage]);

                }

            }

            if (done)

      {

           done(YES);

      }

    

        }

        @catch (NSException *exception) {

            [db rollback];

            debugLog( @"Failed to open database file with message %@ in saveRulesAction", [db lastErrorMessage]);

           

        if (done)

      {

           done(NO);

      }

            

        }

        @finally {

            [db commit];

        }

    }];

}

正确代码:

     

-(void)saveRulesAction:(NSArray*)rules rulesInfo:(NSArray*)ruleInfo rulesDescription:(NSArray*)rulesDescription result:(void(^)(BOOL sucess))done

{

    [self checkDBQueue];

    __block BOOL is_exculate_success = NO;

    [queue inDatabase:^(FMDatabase *db) {


        [db beginTransaction];

        @try{


            for(int i=0;i<[ruleInfo count];i++){

                //delete the rules in db

                BOOL rc = [db executeUpdate:@"delete from rulesAction where ruleType=?",ruleInfo[i]];

                if(!rc){

                    debugLog(@"table rulesAction delete info error! info:%@",[db lastErrorMessage]);

                }

            }

            //ruleType actionType TEXT NOT NULL)"];

            //delete rules description info

            BOOL rc  = [db executeUpdate:@"delete from rulesDescription"];

            if(!rc){

                debugLog(@"table rulesDescription delete info error! info:%@",[db lastErrorMessage]);

            }

            

            if(rulesDescription!=nil){

                //save rules description info

                rc= [db executeUpdate:@"insert into rulesDescription(uuid,displayName,description) values (?,?,?)",rulesDescription[0],rulesDescription[1],rulesDescription[2]];

            }else{

                // rules description is nill

                //debugLog(@"rules description is nil");

            }


            //save all rules and action

            for (int i =0; i<[rules count]; i++) {

                NSArray * rule = rules[i];

                BOOL rc = [db executeUpdate:@"insert into rulesAction(ruleType,actionType,time,actionIndex,ruleLevel,hasDone,rulesKey,ruleTime) values (?,?,?,?,?,?,?,datetime('now'))",rule[0],rule[1],rule[2],rule[3],rule[4],rule[5],rule[6]];

                if(!rc){

                    debugLog(@"saveRulesAction into db failed!  db error info is %@",[currentDB lastErrorMessage]);

                }

            }

            

            is_exculate_success = YES;

        }

        @catch (NSException *exception) {

            [db rollback];

            debugLog( @"Failed to open database file with message %@ in saveRulesAction", [db lastErrorMessage]);

            is_exculate_success = NO;

            

        }

        @finally {

            [db commit];

        }

    }];

    if(done){

        done(is_exculate_success);

    }

}

  问题说明:一个queue的block还没有执行完,就在done  block块中执行了,另外的queue查询;导致程序中出现了两个queue;

  解决过程:

     根据报错情况调查: 

    

- (void)inDatabase:(void (^)(FMDatabase *db))block {

    /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue

     * and then check it against self to make sure we're not about to deadlock. */

    FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);

    assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");

    

    FMDBRetain(self);

   

    dispatch_sync(_queue, ^() {

        NSLog(@"dispatch_sync queue start");

        FMDatabase *db = [self database];

        block(db);

        

        if ([db hasOpenResultSets]) {

            NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");

            

#if defined(DEBUG) && DEBUG

            NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);

            for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {

                FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];

                NSLog(@"query: '%@'", [rs query]);

            }

#endif

        }

        NSLog(@"dispatch_sync queue end");

    });

    

    FMDBRelease(self);

}

   上述代码中居然没有执行这个NSLog(@"dispatch_sync queue end");,就出现了死锁,说明上一个indatabase:还没有执行完毕,另外一个就又开始了,根据程序的执行顺序一一排查,block块外的queue还没有执行完毕,就开是了另外一个indatabase的调用,可见上述代码的问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值