Belle II Software  release-08-01-10
SemaphoreLocker.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <framework/pcore/SemaphoreLocker.h>
9 #include <framework/logging/Logger.h>
10 
11 #include <sys/ipc.h>
12 #include <sys/sem.h>
13 
14 #include <cerrno>
15 #include <cstring>
16 
17 using namespace Belle2;
18 
19 int SemaphoreLocker::create(key_t semkey)
20 {
21  int semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600);
22  if (semid >= 0) {
23  // POSIX doesn't guarantee any particular state of our fresh semaphore
24  int semval = 1; //unlocked state
25  if (semctl(semid, 0, SETVAL, semval) == -1) { //set 0th semaphore to semval
26  B2ERROR("Initializing semaphore with semctl() failed.");
27  }
28  } else if (errno == EEXIST) {
29  semid = semget(semkey, 1, 0600);
30  }
31  if (semid < 0) {
32  B2ERROR("Couldn't create semaphore with semget()! Maybe you have too many semaphores from aborted processes lying around, you can clean those up by running 'clear_basf2_ipc'.");
33  return semid;
34  }
35 
36  return semid;
37 }
38 
39 void SemaphoreLocker::destroy(int semId)
40 {
41  if (semctl(semId, 1, IPC_RMID) == -1) { //semnum=1 has no meaning, ignored
42  B2ERROR("Error in SemaphoreLocker::destroy(), semaphore " << semId << ", error: " << strerror(errno));
43  }
44 }
45 
47 {
48  int ignored = 0;
49  int val = semctl(semId, 0, GETVAL, ignored);
50  return (val == 0); //0: locked, 1: unlocked
51 
52 }
53 
54 namespace {
55  void doSemOp(int semID, int op)
56  {
57  struct sembuf sb;
58  sb.sem_num = 0;
59  sb.sem_op = op;
60  sb.sem_flg = 0;
61  while (semop(semID, &sb, 1) == -1) {
62  if (errno == EINTR) {
63  //interrupted by signal (e.g. window size changed), try again
64  continue;
65  } else {
66  B2FATAL("Another process was aborted, please check previous output for reasons. (" <<
67  strerror(errno) << " for semaphore " << semID << ")");
68  }
69  }
70  }
71 }
73 {
74  doSemOp(m_id, -1);
75 }
76 
78 {
79  doSemOp(m_id, 1);
80 }
81 
static void destroy(int semId)
Destroy the given semaphore.
static int create(key_t semkey)
Create a new semaphore and initialize it.
void unlock()
Unlock the semaphore.
void lock()
Lock the semaphore.
int m_id
semaphore id, see semget(2).
static bool isLocked(int semId)
Return true if the given semaphore is locked.
Abstract base class for different kinds of events.