views:

742

answers:

1

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

+4  A: 

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;
}
Hasturkun
Instead of using number(10023, 10024) to identify the uniqueness of semaphore, can we use string (helloworld, goodbyeworld)?
Yan Cheng CHEOK
What you probably should be using is ftok(http://linux.die.net/man/3/ftok), however note that only 8 bits of proj_id are used
Hasturkun
Thanks! I will try it out once I get access to the machine. One thing is, when shall I call $sem->remove? Initially, I plan to call it at END {#inrease counter back to one. #remove semaphore from system???} block. However, if I remove semaphore from system while there is another process waiting for semaphore's lock, is there any side effect (Mutual exclusion will break, suddenly all waiting process able to grab the resource). Is not, shall I ignore 'remove' call? Will this cause system resource leak?
Yan Cheng CHEOK
I would use a scheduled task which opens the semaphore, then uses stat to check the sem's otime (last semop time) to decide if it should be removed.re: remove behavior, the semctl manpage (http://linux.die.net/man/2/semctl) states all waiting processes will be woken up, with the semop call returning an error (false in the perl case)
Hasturkun