Using dispatch_semaphore_t to wait for objective-c block finish running

I’ve got a method that get c++ based callback as input param(ReplyCallback).

It passes this callback to background task (NSURLSessionDataTask) that send http request and uses this callback in the completionHandler.

Since this callback is used in another thread (on the completionHandler of NSURLSessionDataTask) I used semaphore so it won’t be deleted.

However, I sometimes get The a crash on this code due to the

Thread 14 name:  NSOperationQueue 0x134609be0 (QOS: UNSPECIFIED)

Here’s my code (the relevant parts)

bool Send(Request &req, const std::function<void(bool, Reply)> &ReplyCallback) {

  ....

  NSMutableURLRequest *urlReq = ...;
  dispatch_semaphore_t    sem;
  sem = dispatch_semaphore_create(0);

  NSURLSessionDataTask *_dTask = [session  
  dataTaskWithRequest:urlReq completionHandler:^(NSData * _Nullable data,NSURLResponse * _Nullable response, NSError * _Nullable error)   
  {

     Reply r = ...; 
     ...
     ReplyCallback(true, r);
  }
  [_dTask resume];
  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}

My question is whether using the semaphore is ok ?

No need to use a semaphore there in order to keep the callback alive; the callback won’t be deleted. The only thing the semaphore will do in that context is to prevent the Send function from returning, effectively blocking the caller.

Also, using semaphores to prevent objects from being deleted is quite unusual.

To keep an object alive, the scope in which that object is created should be kept alive or something should hold a strong reference to the object.

I think, the main reason for using the semaphore in that context was to wait for the completion handler. Again, this is quite unusual. What should really happen there is this: the caller of the Send function should wait for the completion handler to fire, not the Send function.

thanks for your reply, so i basically need to make sure that my c++ based callback is valid until it’s being called. I wonder what is the best way to do it without waiting for the callback to finish and stay in that scope…

If you can post your code invoking the Send function, we can start from there.