CUBRID Engine  latest
process_util.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * process_util.c - functions for process manipulation
22  */
23 
24 #include "process_util.h"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 
30 #if defined(WINDOWS)
31 #include <string>
32 #include <Windows.h>
33 #else
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <signal.h>
38 #endif
39 
40 int
41 create_child_process (const char *const argv[], int wait_flag, const char *stdin_file, char *stdout_file,
42  char *stderr_file, int *exit_status)
43 {
44 #if defined(WINDOWS)
45  int new_pid;
46  STARTUPINFO start_info;
47  PROCESS_INFORMATION proc_info;
48  BOOL res;
49  int i, cmd_arg_len;
50  std::string cmd_arg = "";
51  char *cmd_arg_ptr;
52  BOOL inherit_flag = FALSE;
53  HANDLE hStdIn = INVALID_HANDLE_VALUE;
54  HANDLE hStdOut = INVALID_HANDLE_VALUE;
55  HANDLE hStdErr = INVALID_HANDLE_VALUE;
56  BOOL rc;
57 
58  if (exit_status != NULL)
59  {
60  *exit_status = -1;
61  }
62 
63  for (i = 0, cmd_arg_len = 0; argv[i]; i++)
64  {
65  std::string arg = "";
66 
67  arg += "\"";
68  arg += argv[i];
69  arg += "\" ";
70 
71  cmd_arg += arg;
72  cmd_arg_len += arg.size ();
73  }
74 
75  cmd_arg_ptr = strdup (cmd_arg.c_str ());
76 
77  GetStartupInfo (&start_info);
78  start_info.wShowWindow = SW_HIDE;
79 
80  if (stdin_file)
81  {
82  hStdIn = CreateFile (stdin_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
83 
84  if (hStdIn == INVALID_HANDLE_VALUE)
85  {
86  assert (false);
87  return 1;
88  }
89 
90  SetHandleInformation (hStdIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
91  start_info.dwFlags = STARTF_USESTDHANDLES;
92  start_info.hStdInput = hStdIn;
93  inherit_flag = TRUE;
94  }
95  if (stdout_file)
96  {
97  hStdOut =
98  CreateFile (stdout_file, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
99  if (hStdOut == INVALID_HANDLE_VALUE)
100  {
101  assert (false);
102  return 1;
103  }
104  SetHandleInformation (hStdOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
105  start_info.dwFlags = STARTF_USESTDHANDLES;
106  start_info.hStdOutput = hStdOut;
107  inherit_flag = TRUE;
108  }
109  if (stderr_file)
110  {
111  hStdErr =
112  CreateFile (stderr_file, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
113  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
114  if (hStdErr == INVALID_HANDLE_VALUE)
115  {
116  assert (false);
117  return 1;
118  }
119 
120  SetHandleInformation (hStdErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
121  start_info.dwFlags = STARTF_USESTDHANDLES;
122  start_info.hStdError = hStdErr;
123  inherit_flag = TRUE;
124  }
125 
126  res =
127  CreateProcess (argv[0], cmd_arg_ptr, NULL, NULL, inherit_flag, CREATE_NO_WINDOW, NULL, NULL, &start_info,
128  &proc_info);
129  free (cmd_arg_ptr);
130 
131  if (res == FALSE)
132  {
133  return 1;
134  }
135 
136  if (hStdIn != INVALID_HANDLE_VALUE)
137  {
138  rc = CloseHandle (hStdIn);
139  if (rc == FALSE)
140  {
141  assert (false);
142  return 1;
143  }
144  }
145  if (hStdOut != INVALID_HANDLE_VALUE)
146  {
147  rc = CloseHandle (hStdOut);
148  if (rc == FALSE)
149  {
150  assert (false);
151  return 1;
152  }
153  }
154  if (hStdErr != INVALID_HANDLE_VALUE)
155  {
156  rc = CloseHandle (hStdErr);
157  if (rc == FALSE)
158  {
159  assert (false);
160  return 1;
161  }
162  }
163 
164  new_pid = proc_info.dwProcessId;
165 
166  if (wait_flag)
167  {
168  DWORD status = 0;
169 
170  status = WaitForSingleObject (proc_info.hProcess, INFINITE);
171  if (status == WAIT_FAILED)
172  {
173  assert (false);
174  return 1;
175  }
176  rc = GetExitCodeProcess (proc_info.hProcess, &status);
177  if (rc == FALSE)
178  {
179  assert (false);
180  return 1;
181  }
182  if (exit_status != NULL)
183  {
184  *exit_status = status;
185  }
186  rc = CloseHandle (proc_info.hProcess);
187  if (rc == FALSE)
188  {
189  assert (false);
190  return 1;
191  }
192  rc = CloseHandle (proc_info.hThread);
193  if (rc == FALSE)
194  {
195  assert (false);
196  return 1;
197  }
198  return 0;
199  }
200  else
201  {
202  rc = CloseHandle (proc_info.hProcess);
203  if (rc == FALSE)
204  {
205  assert (false);
206  return 1;
207  }
208  rc = CloseHandle (proc_info.hThread);
209  if (rc == FALSE)
210  {
211  assert (false);
212  return 1;
213  }
214  return new_pid;
215  }
216 }
217 #else
218  int pid, rc;
219 
220  if (exit_status != NULL)
221  {
222  *exit_status = -1;
223  }
224 
225  if (wait_flag)
226  {
227  if (signal (SIGCHLD, SIG_DFL) == SIG_ERR)
228  {
229  assert (false);
230  return 1;
231  }
232  }
233  else
234  {
235  if (signal (SIGCHLD, SIG_IGN) == SIG_ERR)
236  {
237  assert (false);
238  return 1;
239  }
240  }
241 
242  pid = fork ();
243 
244  if (pid < 0)
245  {
246  return 1;
247  }
248 
249  if (pid == 0)
250  {
251  FILE *fp;
252 
253  if (stdin_file != NULL)
254  {
255  fp = fopen (stdin_file, "r");
256  if (fp == NULL)
257  {
258  assert (false);
259  return 1;
260  }
261 
262  rc = dup2 (fileno (fp), 0);
263  if (rc == -1)
264  {
265  assert (false);
266  return 1;
267  }
268  rc = fclose (fp);
269  if (rc != 0)
270  {
271  assert (false);
272  return 1;
273  }
274  }
275  if (stdout_file != NULL)
276  {
277  rc = unlink (stdout_file);
278  if (rc == -1)
279  {
280  assert (false);
281  return 1;
282  }
283  fp = fopen (stdout_file, "w");
284  if (fp == NULL)
285  {
286  assert (false);
287  return 1;
288  }
289  rc = dup2 (fileno (fp), 1);
290  if (rc == -1)
291  {
292  assert (false);
293  return 1;
294  }
295  rc = fclose (fp);
296  if (rc != 0)
297  {
298  assert (false);
299  return 1;
300  }
301  }
302  if (stderr_file != NULL)
303  {
304  rc = unlink (stderr_file);
305  if (rc == -1)
306  {
307  assert (false);
308  return 1;
309  }
310  fp = fopen (stderr_file, "w");
311  if (fp == NULL)
312  {
313  assert (false);
314  return 1;
315  }
316  rc = dup2 (fileno (fp), 2);
317  if (rc == -1)
318  {
319  assert (false);
320  return 1;
321  }
322  rc = fclose (fp);
323  if (rc != 0)
324  {
325  assert (false);
326  return 1;
327  }
328  }
329 
330  rc = execv ((const char *) argv[0], (char *const *) argv);
331  assert (false);
332  return rc;
333  }
334 
335  if (wait_flag)
336  {
337  int status = 0;
338 
339  rc = waitpid (pid, &status, 0);
340  if (rc == -1)
341  {
342  assert (false);
343  return 1;
344  }
345  if (exit_status != NULL)
346  {
347  if (WIFEXITED (status))
348  {
349  *exit_status = WEXITSTATUS (status);
350  }
351  else
352  {
353  *exit_status = -2;
354  }
355  }
356  return 0;
357  }
358  else
359  {
360  return pid;
361  }
362 }
363 #endif
#define TRUE
Definition: broker_admin.c:49
#define assert(x)
#define NULL
Definition: freelistheap.h:34
pid_t pid
Definition: dynamic_load.c:955
int create_child_process(const char *const argv[], int wait_flag, const char *stdin_file, char *stdout_file, char *stderr_file, int *exit_status)
Definition: process_util.c:41
static int rc
Definition: serial.c:50
const char ** argv
Definition: dynamic_load.c:952
#define FALSE
Definition: broker_admin.c:50
int i
Definition: dynamic_load.c:954
char * strdup(const char *str)
Definition: porting.c:901