[Exim] Tests needed: semaphores

Top Page
Delete this message
Reply to this message
Author: Philip Hazel
Date:  
To: exim-users
Subject: [Exim] Tests needed: semaphores
I'm considering making use of semaphores in Exim 4 for things like
preventing simultaneous identical ETRN runs. (At present it uses a
hints database.) All the OS that I have tried seem to have the relevant
facilities (the semctl(), semget(), and semop() functions), though not
all are quite the same. I have tried Solaris 8, Linux (RH), IRIX,
FreeBSD, HP-UX, Digital Unix, SunOS4, BSDI, NetBSD and SCO.

I would be grateful if people running other operating systems could run
the attached test program for me, and let me know what happens. See the
comments at the start of the program about running it and what to
expect. It is most likely that if it compiles, it will run OK. There are
some tweaks you can make for certain compiling problems that I
encountered on BSDI and NetBSD. They are also mentioned in the comments.

Thanks,
Philip

-- 
Philip Hazel            University of Cambridge Computing Service,
ph10@???      Cambridge, England. Phone: +44 1223 334714.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>


/* This is a test program for checking out the use of semaphores on Unix 
operating systems. In most systems it compiles right away. The output from 
running it should look something like this:

$ ./a.out
 5779 semaphore 589824 created
 5778 semaphore exists: waiting
 5779 removed semaphore 589824
 5778 semaphore 655360 created
 5778 removed semaphore 655360
$

where the actual numbers will be different every time.

On some operating systems, the program won't compile without modification.
Known culprits in this regard are BSDI and NetBSD. If your compiler complains 
about insufficient arguments for semctl(), then uncomment the following line: 
*/

/* #define SEMCTL_ARG4 (union semun)NULL */

/* Please let me know if you have to do this to get the program to compile. */

/* If after doing this you get complaints that "union semun" is undefined, try 
uncommenting the following definition: */


/***
union semun {
        int val;                  
        struct semid_ds *buf;     
        unsigned short int *array;
};
***/



#define KEYSIG 0x45780000
#define KEYBOT 0x00001234

#ifndef SEMCTL_ARG4
#define SEMCTL_ARG4 NULL
#endif


static void doit(void)
{
pid_t pid = getpid();
key_t key = KEYSIG | KEYBOT;
int i, sem;

for (i = 0; i < 5; i++)
  {
  sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 0600);
  if (sem < 0)
    {
    if (errno == EEXIST)
      {
      printf("%5d semaphore exists: waiting\n", pid);
      sleep(1);
      continue;   
      }  
    else
      { 
      printf("%5d semget failed: %s\n", pid, strerror(errno)); 
      exit(1);
      }  
    } 
  else break;   
  }
  
if (i >= 5)
  {
  printf("%5d timed out\n", pid);
  exit(1);
  }  

printf("%5d semaphore %d created\n", pid, sem);
sleep(1);

if (semctl(sem, 1, IPC_RMID, SEMCTL_ARG4) < 0)
  {
  printf("%5d semctl failed: %s\n", pid, strerror(errno));
  exit(1); 
  } 

printf("%5d removed semaphore %d\n", pid, sem);
}



int main(void)
{
pid_t pid;
key_t key = KEYSIG | KEYBOT;
int status;
int sem = semget(key, 1, 0);

if (sem >= 0)
  {
  printf("** semaphore pre-exists: removing\n");
  if (semctl(sem, 1, IPC_RMID, SEMCTL_ARG4) < 0)
    {
    printf("  semctl failed: %s\n", strerror(errno));
    exit(1); 
    } 
  } 

pid = fork();
doit();
if (pid != 0) wait(&status);
return 0;
}