MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbProcess.hpp
1 /*
2  Copyright 2009 Sun Microsystems, Inc.
3 
4  All rights reserved. Use is subject to license terms.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; version 2 of the License.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 
21 #ifndef NDB_PROCESS_HPP
22 #define NDB_PROCESS_HPP
23 
24 #include <portlib/NdbSleep.h>
25 
27 {
28 #ifdef _WIN32
29  tyepdef DWORD pid_t;
30 #endif
31  pid_t m_pid;
32  BaseString m_name;
33 public:
34 
35  static pid_t getpid()
36  {
37 #ifdef _WIN32
38  return GetCurrentProcessid();
39 #else
40  return ::getpid();
41 #endif
42  }
43 
44  class Args
45  {
46  Vector<BaseString> m_args;
47  public:
48 
49  void add(const char* str)
50  {
51  m_args.push_back(str);
52  }
53 
54  void add(const char* str, const char* str2)
55  {
56  BaseString tmp;
57  tmp.assfmt("%s%s", str, str2);
58  m_args.push_back(tmp);
59  }
60 
61  void add(const char* str, int val)
62  {
63  BaseString tmp;
64  tmp.assfmt("%s%d", str, val);
65  m_args.push_back(tmp);
66  }
67 
68  const Vector<BaseString>& args(void) const
69  {
70  return m_args;
71  }
72 
73  };
74 
75  static NdbProcess* create(const BaseString& name,
76  const BaseString& path,
77  const BaseString& cwd,
78  const Args& args)
79  {
80  NdbProcess* proc = new NdbProcess(name);
81  if (!proc)
82  {
83  fprintf(stderr, "Failed to allocate memory for new process\n");
84  return NULL;
85  }
86 
87  // Check existence of cwd
88  if (cwd.c_str() && access(cwd.c_str(), F_OK) != 0)
89  {
90  fprintf(stderr,
91  "The specified working directory '%s' does not exist\n",
92  cwd.c_str());
93  delete proc;
94  return NULL;
95  }
96 
97  if (!start_process(proc->m_pid, path.c_str(), cwd.c_str(), args))
98  {
99  fprintf(stderr,
100  "Failed to create process '%s'\n", name.c_str());
101  delete proc;
102  return NULL;
103  }
104  return proc;
105  }
106 
107  bool stop(void)
108  {
109  int ret = kill(m_pid, 9);
110  if (ret != 0)
111  {
112  fprintf(stderr,
113  "Failed to kill process %d, ret: %d, errno: %d\n",
114  m_pid, ret, errno);
115  return false;
116  }
117  printf("Stopped process %d\n", m_pid);
118  return true;
119  }
120 
121  bool wait(int& ret, int timeout = 0)
122  {
123  int retries = 0;
124  int status;
125  while (true)
126  {
127  pid_t ret_pid = waitpid(m_pid, &status, WNOHANG);
128  if (ret_pid == -1)
129  {
130  fprintf(stderr,
131  "Error occured when waiting for process %d, ret: %d, errno: %d\n",
132  m_pid, status, errno);
133  return false;
134  }
135 
136  if (ret_pid == m_pid)
137  {
138  if (WIFEXITED(status))
139  ret = WEXITSTATUS(status);
140  else if (WIFSIGNALED(status))
141  ret = WTERMSIG(status);
142  else
143  ret = 37; // Unknown exit status
144 
145  printf("Got process %d, status: %d, ret: %d\n", m_pid, status, ret);
146  return true;
147  }
148 
149  if (timeout == 0)
150  return false;
151 
152  if (retries++ > timeout*10)
153  {
154  fprintf(stderr,
155  "Timeout when waiting for process %d\n", m_pid);
156  return false;
157  }
158  NdbSleep_MilliSleep(10);
159  }
160  assert(false); // Never reached
161  }
162 
163 private:
164 
165  NdbProcess(BaseString name) :
166  m_name(name)
167  {
168  m_pid = -1;
169  }
170 
171  static bool start_process(pid_t& pid, const char* path,
172  const char* cwd,
173  const Args& args)
174  {
175 #ifdef _WIN32
176 #else
177  int retries = 5;
178  pid_t tmp;
179  while ((tmp = fork()) == -1)
180  {
181  fprintf(stderr, "Warning: 'fork' failed, errno: %d - ", errno);
182  if (retries--)
183  {
184  fprintf(stderr, "retrying in 1 second...\n");
185  NdbSleep_SecSleep(1);
186  continue;
187  }
188  fprintf(stderr, "giving up...\n");
189  return false;
190  }
191 
192  if (tmp)
193  {
194  pid = tmp;
195  printf("Started process: %d\n", pid);
196  return true;
197  }
198  assert(tmp == 0);
199 
200  if (cwd && chdir(cwd) != 0)
201  {
202  fprintf(stderr, "Failed to change directory to '%s', errno: %d\n", cwd, errno);
203  exit(1);
204  }
205 
206  // Concatenate arguments
207  BaseString args_str;
208  args_str.assign(args.args(), " ");
209 
210  char **argv = BaseString::argify(path, args_str.c_str());
211  //printf("name: %s\n", path);
212  execv(path, argv);
213 
214  fprintf(stderr, "execv failed, errno: %d\n", errno);
215  exit(1);
216 #endif
217  }
218 };
219 
220 #endif