Instrument Neutral Distributed Interface INDI  2.0.2
ProcessController.cpp
Go to the documentation of this file.
1 #include <system_error>
2 #include <unistd.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <sys/socket.h>
7 #include <signal.h>
8 #include <dirent.h>
9 #include <errno.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 
13 #include "ProcessController.h"
14 
16  pid = -1;
17  cmd = "<unstarted>";
18  status = 0;
19 }
20 
22 }
23 
24 
26  if (pid == -1) {
27  throw std::runtime_error(cmd + " is done - cannot check open fd count");
28  }
29 #ifdef __linux__
30  std::string path = "/proc/" + std::to_string(pid) + "/fd";
31 
32  int count = 0;
33  auto dirp = opendir(path.c_str());
34  if (dirp == nullptr) {
35  throw std::system_error(errno, std::generic_category(), "opendir error: " + path);
36  }
37 
38  for(auto dp = readdir(dirp); dp != nullptr; dp = readdir(dirp)) {
39  std::string name = dp->d_name;
40  if (name.length() == 0 || name[0] == '.') {
41  continue;
42  }
43  count++;
44  }
45  closedir(dirp);
46  return count;
47 #else
48  return 0;
49 #endif
50 }
51 
52 void ProcessController::checkOpenFdCount(int expected, const std::string & msg) {
53 #ifdef __linux__
54  int count = getOpenFdCount();
55  if (count != expected) {
56  throw std::runtime_error(msg + " " + cmd + " open file count is " + std::to_string(count) + " - expected: " + std::to_string(expected));
57  }
58 #else
59  (void)expected;
60  (void)msg;
61 #endif
62 }
63 
64 void ProcessController::start(const std::string & path, const std::vector<std::string> & args)
65 {
66  if (pid != -1) {
67  throw std::runtime_error(cmd + " already running");
68  }
69 
70  cmd = path;
71 
72  int argCount = 0;
73  argCount = args.size();
74  const char * fullArgs[argCount + 2];
75  fullArgs[0] = path.c_str();
76  for(int i = 0; i < argCount ; i++) {
77  fullArgs[i + 1] = args[i].c_str();
78  }
79  fullArgs[1 + argCount] = nullptr;
80  fprintf(stderr, "Running ");
81  for(int i = 0; i < 2+ argCount ; ++i) {
82  fprintf(stderr, " %s", fullArgs[i] ? fullArgs[i] : "<null>");
83  }
84  fprintf(stderr, "\n");
85  // Do fork & exec for the indiserver binary
86  pid = fork();
87  if (pid == -1) {
88  throw std::system_error(errno, std::generic_category(), "fork error");
89  }
90  if (pid == 0) {
91  std::string error = "exec " + path;
92  // TODO : Close all file descriptor
93  execv(fullArgs[0], (char * const *) fullArgs);
94 
95  // Child goes here....
96  perror(error.c_str());
97  ::exit(1);
98  }
99 }
100 
102  join();
103  expectExitCode(exitCode);
104 }
105 
107  if (pid == -1) {
108  return;
109  }
110  ::kill(pid, SIGKILL);
111 }
112 
114  if (pid == -1) {
115  return;
116  }
117  pid_t waited = waitpid(pid, &status, 0);
118  if (waited == -1) {
119  throw std::system_error(errno, std::generic_category(), "waitpid error");
120  }
121  pid = -1;
122 }
123 
125  if (pid == -1) {
126  return;
127  }
128 
129  pid_t waited = waitpid(pid, &status, WNOHANG);
130  if (waited == -1) {
131  throw std::system_error(errno, std::generic_category(), "waitpid error");
132  }
133  if (waited == 0) {
134  // No child found... Still running
135  throw std::runtime_error("Process " + cmd + " not done");
136  }
137 
138  pid = -1;
139 }
140 
142  if (pid != -1) {
143  pid_t waited = waitpid(pid, &status, WNOHANG);
144  if (waited == -1) {
145  throw std::system_error(errno, std::generic_category(), "waitpid error");
146  }
147  if (waited != 0) {
148  // Process terminated
149  pid = -1;
150  return;
151  }
152  }
153 
154  throw std::runtime_error("Process terminated unexpectedly");
155 }
156 
158  expectDone();
159 
160  if (!WIFEXITED(status)) {
161  if (WIFSIGNALED(status)) {
162  throw std::runtime_error(cmd + " got signal " + strsignal(WTERMSIG(status)));
163  }
164  // Not sure this is possible at all
165  throw std::runtime_error(cmd + " exited abnormaly");
166  }
167  int actual = WEXITSTATUS(status);
168  if (actual != e) {
169  throw std::runtime_error("Wrong exit code for " + cmd + ": got " + std::to_string(actual) + " - expecting: " + std::to_string(e));
170  }
171 }
void start(const std::string &path, const std::vector< std::string > &args)
void checkOpenFdCount(int expected, const std::string &msg)
void waitProcessEnd(int expectedExitCode)
int errno
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:23613