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