Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dispatch_semaphore_wait does not wait on semaphore

I have developed the following method, which checks the app's ability to communicate with the server. The method performs a simple query and knows that if it gets a result, the app should be connected (basic ping mechanism).

- (BOOL)isAppConnected
{
    __block BOOL isConnected = NO;

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    [[SFRestAPI sharedInstance] performSOQLQuery:@"SELECT id FROM Account LIMIT 1"
                                           failBlock:^(NSError *e) {
                                               isConnected = NO;
                                               NSLog(@"NOT CONNECTED %@", e);
                                               NSLog(@"fail block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);

                                               dispatch_semaphore_signal(semaphore);

                                           } completeBlock:^(NSDictionary *dict) {
                                               isConnected = YES;
                                               NSLog(@"%@", dict);
                                               NSLog(@"complete block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);

                                               dispatch_semaphore_signal(semaphore);
                                           }];

    // if the wait times-out we will receive a non-zero result and can assume no connection to SF
    //When using: DISPATCH_TIME_FOREVER the app hangs forever!!
    int waitResult = dispatch_semaphore_wait(semaphore, 30 * NSEC_PER_SEC); 
    NSLog(@"waitResult: %d", waitResult);

    return isConnected;
}

I am using the 'dispatch_semaphore_wait' as suggested in the Apple documentation

My goal is to wait on the response or a short timeout to figure out if we really have a valid connection.

With the code above, 'dispatch_semaphore_wait' never actually waits, i.e. execution does not stop at that line but it continues immediately (always returning 49 as the result to the dispatch_semaphore_wait call). That is unless I use DISPATCH_TIME_FOREVER in which case the app hangs forever...

At the moment I am calling this method from the main thread. I am aware that this is a bad idea, but I wanted to see this working as expected before refactoring.

What could be causing this behaviour? Thanks.

like image 542
edoDev Avatar asked Dec 06 '22 00:12

edoDev


2 Answers

The parameter for dispatch_semaphore_wait is not a delay, but the time when the semaphore should wake up. Yours will wake up 30 seconds after Midnight, Jan 1st. 1970 (or 2001, not sure). Use the dispatch_time function.

like image 142
gnasher729 Avatar answered Dec 20 '22 05:12

gnasher729


- (BOOL)isAppConnected
{
    __block BOOL isConnected = NO;

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    // Add this code...
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [[SFRestAPI sharedInstance] performSOQLQuery:@"SELECT id FROM Account LIMIT 1"
                                           failBlock:^(NSError *e) {
                                               isConnected = NO;
                                               NSLog(@"NOT CONNECTED %@", e);
                                               NSLog(@"fail block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);

                                               dispatch_semaphore_signal(semaphore);

                                           } completeBlock:^(NSDictionary *dict) {
                                               isConnected = YES;
                                               NSLog(@"%@", dict);
                                               NSLog(@"complete block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);

                                               dispatch_semaphore_signal(semaphore);
                                           }];
    });

    int waitResult = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"waitResult: %d", waitResult);

    return isConnected;
}
like image 35
Changwook Jeong Avatar answered Dec 20 '22 07:12

Changwook Jeong