Belle II Software  release-05-01-25
framework-pcore-clear_ipcs.cc
1 //+
2 // Description : Remove uncleaned IPC resources (should not usually be necessary)
3 //
4 // Author : Ryosuke Itoh, IPNS, KEK
5 // Date : 30 - Dec - 2013
6 //
7 
8 #include <dirent.h>
9 #include <cstdio>
10 #include <unistd.h>
11 #include <cstring>
12 #include <cstdlib>
13 
14 #include <sys/ipc.h>
15 #include <sys/shm.h>
16 #include <sys/sem.h>
17 
18 int main(int argc, char** argv)
19 {
20  int mode = 2; // unnamed IPC resources only
21  if (argc > 1) {
22  if (strcmp(argv[1], "all") == 0)
23  mode = 0;
24  else if (strcmp(argv[1], "named") == 0)
25  mode = 1;
26  else if (strcmp(argv[1], "unnamed") == 0)
27  mode = 2;
28  else {
29  printf("Usage : clear_basf2_ipc {all|named|unnamed} \n");
30  printf("all: all IPCs, named: named IPCs only, unnamed: basf2 internal IPCs only(default)\n");
31 
32  printf("\n Cleans up inter-process communication (IPC) resources left behind if basf2 crashes.\n\n");
33  printf("Normally, this shouldn't be necessary, but resources may remain after a bad crash or basf2 is killed using SIGKILL.\n");
34  printf("Resources currently in use are not touched.\n");
35  printf("The return code is set to 1 when uncleaned resources are found, 0 if none are found, and -1 on error.\n");
36  return -1;
37  }
38  }
39 
40  DIR* dir;
41  if ((dir = opendir("/tmp")) != nullptr) {
42  int ret = 0;
43  struct dirent* ent;
44  while ((ent = readdir(dir)) != nullptr) {
45  if (strncmp(ent->d_name, "SHM", 3) == 0) {
46  // printf ("%s\n", ent->d_name);
47  int shmid, semid;
48  char name[256];
49  sscanf(ent->d_name, "SHM%d-SEM%d-%255s", &shmid, &semid, name);
50  // printf ( "name : %s - shmid = %d, semid = %d\n", name, shmid, semid );
51  int unnamed = strcmp(name, "UNNAMED");
52  bool deleted = false;
53  bool stale = false;
54  if (shmid > 0) {
55  if (mode == 0 || (unnamed == 0 && mode == 2) ||
56  (unnamed != 0 && mode == 1)) {
57 
58  shmid_ds shmInfo;
59  if (shmctl(shmid, IPC_STAT, &shmInfo) != 0) {
60  printf("Removing stale file %s\n", ent->d_name);
61  stale = true; //already gone (note: stale files do not produce non-zero return code)
62  } else {
63  //Don't remove SHM segments which still have a process attached
64  //Note that nattch counter is decreased by both shmdt() and exit()
65  if (shmInfo.shm_nattch != 0) {
66  printf("/tmp/%s still has %ld processes attached, skipped.\n", ent->d_name, shmInfo.shm_nattch);
67  continue;
68  }
69 
70  if (shmctl(shmid, IPC_RMID, (struct shmid_ds*) nullptr) == 0) {
71  printf("SHM %d deleted. ", shmid);
72  deleted = true;
73  }
74  }
75  }
76  }
77  if (semid > 0) {
78  if (mode == 0 || (unnamed == 0 && mode == 2) ||
79  (unnamed != 0 && mode == 1)) {
80  if (semctl(semid, 1, IPC_RMID) == 0) {
81  printf("SEM %d deleted. ", semid);
82  deleted = true;
83  }
84  }
85  }
86  if (deleted or stale) {
87  ret = 1;
88  printf("\n");
89  char strbuf[1024];
90  snprintf(strbuf, 1024, "/tmp/%s", ent->d_name);
91  unlink(strbuf);
92  if (unnamed != 0) {
93  snprintf(strbuf, 1024, "/tmp/%s_%s", getenv("USER"), name);
94  unlink(strbuf);
95  }
96  }
97  }
98  }
99  closedir(dir);
100  return ret;
101  } else {
102  perror("");
103  return -1;
104  }
105 }
main
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:77