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