develooper Front page | perl.perl5.porters | Postings from January 2001

Problems with SysV semaphores and an offtopic question

From:
Alexander Farber
Date:
January 2, 2001 08:49
Subject:
Problems with SysV semaphores and an offtopic question
Message ID:
3A520681.D35DABDB@cpan.org
Hi all,

I have read perldoc perlxs, perlxstut and am currently
reading perlguts, so I don't understand much of the Perl 
source code yet... 

However I suspect that there are few problems with the 
SysV-semaphores in the Perl source code and in the modules 
IPC::Shareable and IPC::ShareLite:

1) In the file perl-5.6.1-TRIAL1/doio.c: I don't see
   any loop in the Perl_do_semop(). Does it mean that
   for a set of operations, semop(2) is being called
   several times? If so, then it is not atomic.

2) The module IPC::Shareable calls

    $sem->op(SEM_LOCKER, SHM_LOCK_WAIT, SEM_UNDO,
             SEM_LOCKER, SHM_LOCK_EX,   SEM_UNDO);

   And the op() in perl-5.6.1-TRIAL1/ext/IPC/SysV/Semaphore.pm 
   calls Perl's semop. So the locking method of the 
   IPC::Shareable module is broken (not atomic) isn't it?

3) In the _tie() subroutine of the IPC::Shareable
   no semctl(2) is called after semget(2), so according
   to R. Stevens "UNIX Network Programming"-book (the 
   chapter "Initialization of Semaphore Value") the 
   semaphore is not initialized correctly.

4) IPC::Shareable fails "make test" on OpenBSD 2.8 and
   Solaris 2.6. I know that this probably doesn't belong
   to this mailing list, but the module author has never
   replied my e-mails, so I will try here...

5) In the module IPC::ShareLite (sharelite.c) the semaphore 
   ops are initialized like this:

static struct sembuf ex_lock[3] = {
  { 1, 0, 0 },        /* wait for readers to finish */
  { 2, 0, 0 },        /* wait for writers to finish */
  { 2, 1, SEM_UNDO }  /* assert write lock */
};

static struct sembuf ex_lock_nb[3] = {
  { 1, 0, IPC_NOWAIT },             /* wait for readers to finish */
  { 2, 0, IPC_NOWAIT },             /* wait for writers to finish */
  { 2, 1, (SEM_UNDO | IPC_NOWAIT) } /* assert write lock */
};

   But in the next chapter of the UNP-book, Stevens
   says, that struct sembuf shouldn't be initialized 
   statically, because it can contain further members.

6) In the same file of IPC::ShareLite

    /* If they currently have a shared lock, remove it */
    if (share->lock & LOCK_SH) {
      if (RM_SH_LOCK(share->semid) < 0)
        return -1;
      share->lock = 0;
    }
    if (flags & LOCK_NB) { /* non-blocking request */
      if (GET_EX_LOCK_NB(share->semid) < 0) {
        if (errno == EAGAIN) /* would we have blocked? */
          return 1;
        return -1;
      }
    } else { /* blocking request */
      if (GET_EX_LOCK(share->semid) < 0)
        return -1;
    }

   Removing the shared lock and after that to get 
   the exclusive lock is probably not so good?

7) And here is my offtopic question: what is the
   advantage of using the locking schema like in these
   both modules? It is also used in the mm library
   ( http://www.engelschall.com/sw/mm/ ):

      mm_core_dolock[0].sem_num   = 0;
      mm_core_dolock[0].sem_op    = 0;
      mm_core_dolock[0].sem_flg   = 0;
      mm_core_dolock[1].sem_num   = 0;
      mm_core_dolock[1].sem_op    = +1;
      mm_core_dolock[1].sem_flg   = SEM_UNDO;

      mm_core_dounlock[0].sem_num = 0;
      mm_core_dounlock[0].sem_op  = -1;
      mm_core_dounlock[0].sem_flg = SEM_UNDO;
   
   As I understand, 0 means here "unlocked" and 1 means 
   "locked". Since sem_op = +1 doesn't block, it is pre-
   pended by the sem_op = 0.

   But isn't it simpler to have it other way round:

      mm_core_dolock[0].sem_num   = 0;
      mm_core_dolock[0].sem_op    = -1;
      mm_core_dolock[0].sem_flg   = SEM_UNDO;

      mm_core_dounlock[0].sem_num = 0;
      mm_core_dounlock[0].sem_op  = +1;
      mm_core_dounlock[0].sem_flg = SEM_UNDO;

   Here 0 means "locked" and 1 means "unlocked".
   The semaphore value should be initialized to 1.

   I suspect that the first method is somehow better
   if a process holding the lock dies. But how exactly?
   Both methods use SEM_UNDO, so the semaphore value
   will be restored if a process dies, won't it?

   Also the latter method is probably better for AIX,
   because the order of semaphor ops is not guaranteed
   there, when calling semop(2).

I would be glad to get some comments on my mail, because
I am trying to write my own shared memory Perl-module.

Regards
Alex

PS: Maurice, sorry for not sending the complaints about
    IPC::SharedLite first personally to you, but maybe
    it will be good to discuss them on the p5p-list?


--
http://home.t-online.de/home/Alexander.Farber/



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About