iOS Semaphore Problems

Semaphore FlagUPDATE 29/04/2014: There is an update to go along with this post.

Originally for my semaphore I used an Apple specific one that used variable type semaphore_t.

But recently I decided to use a more generic unix one sem_t but started having trouble since it failed to create one.

After a bit of changing the code, I found the call to sem_init() always failed, returning an error code on iOS.

The only way I could get it to work was to use sem_open() with the O_CREAT flag.

//
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
 
//
sem_t * CreateSemaphore( const char * inName, const int inStartingCount )
{
	sem_t * semaphore = sem_open( inName, O_CREAT, 0644, inStartingCount );
 
	//
	if( semaphore == SEM_FAILED )
	{
		switch( errno )
		{
		case EEXIST:
			printf( "Semaphore with name '%s' already exists.\n", inName );
			break;
 
		default:
			printf( "Unhandled error: %d.\n", errno );
			break;
		}
 
		//
		assert(false);
		return SEM_FAILED;
	}
 
	//
	return semaphore;
}

 

This code however is flawed in that if the semaphore already exists it will use that one instead. So I tried to BitOR the flag O_EXCL to O_CREAT so it asserted if the semaphore existed already.

That worked, however now whenever the app didn’t shutdown correctly, the semaphore would not be destroyed and running again would fail since it already existed. I have not yet found a way around this.

Finally to destroy the semaphore, you need to close it with sem_close() instead of sem_destroy().

//
bool DestroySemaphore( sem_t * inSemaphore )
{
	int retErr = sem_close( inSemaphore );
 
	//
	if( retErr == -1 )
	{
		//
		switch( errno )
		{
		case EINVAL:
			printf( "inSemaphore is not a valid sem_t object." );
			break;
 
		default:
			printf( "Unhandled error: %d.\n", errno );
			break;
		}
 
		//
		assert(false);
		return false;
	}
 
	//
	return true;
}
 
//
void SignalSemaphore( sem_t * inSemaphore )
{
	sem_post( inSemaphore );
}
 
//
void WaitSemaphore( sem_t * inSemaphore )
{
	sem_wait( inSemaphore );
}
 
//
bool TryWaitSemaphore( sem_t * inSemaphore )
{
	int retErr = sem_trywait( inSemaphore );
 
	//
	if( retErr == -1 )
	{
		//
		if( errno != EAGAIN )
		{
			printf( "Unhandled error: %d\n", errno );
			assert( false );
		}
 
		//
		return false;
	}
 
	//
	return true;
}