For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > November 2004 > Need Help with semaphores









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Need Help with semaphores
Zack

2004-11-19, 8:57 pm

Hi,

Can someone please, explain to me why the following code fails.
In short, I am receiving message: "ERROR: 'unlock' invalid semcnt=0"
So I thought that I probably have a race condition here and decided to
add the second synchronization to protect semcnt (I've added zLock()
and zUnlock()).
However, after that it just deadlocks.
I am not very proficient with concurrent programming and semaphores.
I am on Solaris 9.


variables:
semcnt, semaphore, z_sem are private member variables

int wmsCache::unlock()
{
int rc;

if (zLock()) {perror("ERROR: zLock() failed in unlock()\n");
return -1;}

if (semcnt > 1)
{
semcnt--;
return 0;
}
if (semcnt <= 0)
{
perror("ERROR: 'unlock' invalid semcnt=%d\n", semcnt);
if (zUnlock())
perror("ERROR: zUnlock() failed in unlock()\n");
return -1;
}
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = SEM_UNDO;
rc = semop(semaphore, &buf, 1);
if (rc == -1)
{
perror("ERROR: problems unlocking semphore\n");
if (zUnlock())
perror("ERROR: zUnlock() failed in unlock()\n");
return -1;
}
semcnt--;

if (zUnlock()){dbg("ERROR: zUnlock() failed in unlock()\n");
return -1;}

return rc;
}

int wmsCache::lock()
{
int rc;
struct sembuf buf;

if (zLock()){perror("ERROR: zLock() failed in unlock()\n"); return
-1;}
if (semcnt > 0)
{
semcnt++;
return 0;
}
if (semcnt < 0)
{
perror("ERROR: 'lock' invalid semcnt=%d\n", semcnt);
if (zUnlock())
perror("ERROR: zUnlock() failed in unlock()\n");
return -1;
}

buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = SEM_UNDO;
for(rc = semop(semaphore, &buf, 1);
(rc < 0) && (errno == EINTR);
rc = semop(semaphore, &buf, 1))
{
if (rc == -1)
{
perror("ERROR: problems locking semphore\n");
if (zUnlock())
perror("ERROR: zUnlock() failed in unlock()\n");
return -1;
}
}
semcnt++;

if (zUnlock()){perror("ERROR: zUnlock() failed in unlock()\n");
return -1;}

return rc;
}

int wmsCache::zUnlock()
{
int rc;

struct sembuf zBuf;
zBuf.sem_num = 0;
zBuf.sem_op = 1;
zBuf.sem_flg = SEM_UNDO;
rc = semop(z_sem, &zBuf, 1);
if (rc == -1)
{
perror("ERROR: problems unlocking semphore in zUnlock()\n");
return -1;
}

return rc;
}

int wmsCache::zLock()
{
int rc;
struct sembuf zBuf;

zBuf.sem_num = 0;
zBuf.sem_op = -1;
zBuf.sem_flg = SEM_UNDO;
for(rc = semop(z_sem, &zBuf, 1);
(rc < 0) && (errno == EINTR);
rc = semop(z_sem, &zBuf, 1))
{
if (rc == -1)
{
perror("ERROR: problems locking semphore in zLock()\n");
return -1;
}
}

return rc;
}
Joe Seigh

2004-11-19, 8:57 pm



Zack wrote:
>
> Hi,
>
> Can someone please, explain to me why the following code fails.
> In short, I am receiving message: "ERROR: 'unlock' invalid semcnt=0"
> So I thought that I probably have a race condition here and decided to
> add the second synchronization to protect semcnt (I've added zLock()
> and zUnlock()).
> However, after that it just deadlocks.
> I am not very proficient with concurrent programming and semaphores.
> I am on Solaris 9.


What is semcnt? If it's initlized to zero then it should go to zero
on the last unlock.

And yes you do need a lock to protect incrementing and decrementing semcnt
sonce those aren't atomic.

Also SEM_UNDO is a bad idea. Your shared resource and semcnt will be left
in an undefined state.

Joe Seigh
Zack

2004-11-23, 3:58 pm

Joe Seigh <jseigh_01@xemaps.com> wrote in message news:<419E5EFD.25C4E612@xemaps.com>...
> Zack wrote:
>
> What is semcnt? If it's initlized to zero then it should go to zero
> on the last unlock.
>
> And yes you do need a lock to protect incrementing and decrementing semcnt
> sonce those aren't atomic.
>
> Also SEM_UNDO is a bad idea. Your shared resource and semcnt will be left
> in an undefined state.
>
> Joe Seigh


Thanks a bunch for the hint, Joe.
The problem was that I forgot to release the z_sem in unlock()/lock()
in
if (semcnt > 1)
{
semcnt--;
// Now I put zUnlock() in here
return 0;
}

and
if (semcnt > 0)
{
semcnt++;
// Now I put zUnlock() in here
return 0;
}

However, here is another thing that was actually the original problem,
which
I was trying to fix but this modification did not quite get it.
Please bear with me on this.

I have a sort of server application that listens for events and
process them according to their type. For every event that the server
catches I create a POSIX thread, so those events can be processed
concurrently.

Those events are triggered by separate programs/processes. Now, the
server and those programs share the same shared library that
implements cache object where I have the synchronization that I've
already shown in this code.

The problem is that it works while the number of threads on the server
do not exceed 60-70.
After these magic numbers are passed, I experience a deadlock on the
processes that trigger events -- all of them hang on semop. In this
situation if I kill those processes, and restart some of them, so that
number of threads in the server do not exceed 60-70 the programs run
fine. Can some one give me an idea what can be wrong. I can't find
any deadlock situation in the code (Of course it does not mean that
there aren't any).

Any help is VERY appreciated
Pascal Bourguignon

2004-11-23, 3:58 pm

uzmargov@yahoo.com (Zack) writes:
> The problem is that it works while the number of threads on the server
> do not exceed 60-70.
> After these magic numbers are passed, I experience a deadlock on the
> processes that trigger events -- all of them hang on semop. In this
> situation if I kill those processes, and restart some of them, so that
> number of threads in the server do not exceed 60-70 the programs run
> fine. Can some one give me an idea what can be wrong. I can't find
> any deadlock situation in the code (Of course it does not mean that
> there aren't any).


What about : man semop
man semctl
man semget ?

Pay special attention to occurences of "SEMMNI" or "SEMMNS".

--
__Pascal Bourguignon__ http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com