Question

I have a Perl CGI program that executes under mod_perl. Within the program, I would like to prevent a resource from accessing by multiple processes at the same time.

# Semaphore Initialization Code
# 10023 is unique id, and this id will be same across different apache process.
# 1, Only one semaphore being created.
# 0722, as all process will be execute under apache account. Hence, they will all having '7' privilege.
my $sem = new IPC::Semaphore(10023, 1, 0722 | IPC_CREAT); # Code(1)
# Set 0th (one and only one) semaphore's value to 1, As I want to use this semaphore as mutex.
$sem->setval(0, 1);                                       # Code(2)

The problem is :

  1. How can I make Code(1) create a new semaphore ONLY when the semaphore if the 10023 id has never being created before, either by same process or other processes?
  2. How can I execute Code(2) ONLY the first time I create the semaphore with 10023 id? A semaphore shall be only initialized ONE TIME.

Another approach is to create an empty file for locking purpose. However, this will end up of having thousands of temporary files. link text

Was it helpful?

Solution

Adding the IPC_EXCL flag causes the underlying semget to either create a new semaphore or fail. You can use this to get the effect you want.

This should work for you:

#Attempt to create (but not get existing) semaphore
my $sem = IPC::Semaphore->new(10023, 1, 0722 | IPC_CREAT | IPC_EXCL);
if ($sem) {
    #success, semaphore created, proceed to set.
    print "new semaphore\n";
    $sem->setval(0, 1);
}
else {
    #obtain the semaphore normally
    print "existing semaphore\n";
    $sem = IPC::Semaphore->new(10023, 1, 0722); #no IPC_CREAT here
    die "could not obtain semaphore?" unless $sem;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top