gspawn.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * Spawning processes.
  3. *
  4. * Author:
  5. * Gonzalo Paniagua Javier (gonzalo@novell.com
  6. *
  7. * (C) 2006 Novell, Inc.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining
  10. * a copy of this software and associated documentation files (the
  11. * "Software"), to deal in the Software without restriction, including
  12. * without limitation the rights to use, copy, modify, merge, publish,
  13. * distribute, sublicense, and/or sell copies of the Software, and to
  14. * permit persons to whom the Software is furnished to do so, subject to
  15. * the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be
  18. * included in all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. #include <config.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <errno.h>
  32. #include <fcntl.h>
  33. #include <sys/types.h>
  34. #include <glib.h>
  35. #ifdef HAVE_UNISTD_H
  36. #ifndef __USE_GNU
  37. #define __USE_GNU
  38. #endif
  39. #include <unistd.h>
  40. #endif
  41. #ifdef HAVE_SYS_SELECT_H
  42. #include <sys/select.h>
  43. #endif
  44. #ifdef HAVE_SYS_TIME_H
  45. #include <sys/time.h>
  46. #endif
  47. #ifdef HAVE_SYS_WAIT_H
  48. #include <sys/wait.h>
  49. #endif
  50. #ifdef HAVE_SYS_RESOURCE_H
  51. # include <sys/resource.h>
  52. #endif
  53. #ifdef G_OS_WIN32
  54. #include <io.h>
  55. #include <winsock2.h>
  56. #define open _open
  57. #define close _close
  58. #define read _read
  59. #define write _write
  60. /* windows pipe api details: http://msdn2.microsoft.com/en-us/library/edze9h7e(VS.80).aspx */
  61. #define pipe(x) _pipe(x, 256, 0)
  62. #endif
  63. #if HAVE_G_SPAWN
  64. #define set_error(msg, ...) do { if (gerror != NULL) *gerror = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
  65. #define set_error_cond(cond,msg, ...) do { if ((cond) && gerror != NULL) *gerror = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
  66. #define set_error_status(status,msg, ...) do { if (gerror != NULL) *gerror = g_error_new (G_LOG_DOMAIN, status, msg, __VA_ARGS__); } while (0)
  67. #define NO_INTR(var,cmd) do { (var) = (cmd); } while ((var) == -1 && errno == EINTR)
  68. static void
  69. mono_close_pipe (int p [2])
  70. {
  71. close (p [0]);
  72. close (p [1]);
  73. }
  74. #if defined(__APPLE__)
  75. #if defined (TARGET_OSX)
  76. /* Apple defines this in crt_externs.h but doesn't provide that header for
  77. * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
  78. * in fact exist on all implementations (so far)
  79. */
  80. G_BEGIN_DECLS
  81. gchar ***_NSGetEnviron(void);
  82. G_END_DECLS
  83. #define environ (*_NSGetEnviron())
  84. #else
  85. static char *mono_environ[1] = { NULL };
  86. #define environ mono_environ
  87. #endif /* defined (TARGET_OSX) */
  88. #elif defined(_MSC_VER)
  89. /* MS defines this in stdlib.h */
  90. #else
  91. G_BEGIN_DECLS
  92. extern char **environ;
  93. G_END_DECLS
  94. #endif
  95. static int
  96. safe_read (int fd, gchar *buffer, gint count, GError **gerror)
  97. {
  98. int res;
  99. NO_INTR (res, read (fd, buffer, count));
  100. set_error_cond (res == -1, "%s", "Error reading from pipe.");
  101. return res;
  102. }
  103. static int
  104. read_pipes (int outfd, gchar **out_str, int errfd, gchar **err_str, GError **gerror)
  105. {
  106. fd_set rfds;
  107. int res;
  108. gboolean out_closed;
  109. gboolean err_closed;
  110. GString *out = NULL;
  111. GString *err = NULL;
  112. gchar *buffer = NULL;
  113. gint nread;
  114. out_closed = (outfd < 0);
  115. err_closed = (errfd < 0);
  116. if (out_str) {
  117. *out_str = NULL;
  118. out = g_string_new ("");
  119. }
  120. if (err_str) {
  121. *err_str = NULL;
  122. err = g_string_new ("");
  123. }
  124. do {
  125. if (out_closed && err_closed)
  126. break;
  127. FD_ZERO (&rfds);
  128. if (!out_closed && outfd >= 0)
  129. FD_SET (outfd, &rfds);
  130. if (!err_closed && errfd >= 0)
  131. FD_SET (errfd, &rfds);
  132. res = select (MAX (outfd, errfd) + 1, &rfds, NULL, NULL, NULL);
  133. if (res > 0) {
  134. if (buffer == NULL)
  135. buffer = g_malloc (1024);
  136. if (!out_closed && FD_ISSET (outfd, &rfds)) {
  137. nread = safe_read (outfd, buffer, 1024, gerror);
  138. if (nread < 0) {
  139. close (errfd);
  140. close (outfd);
  141. return -1;
  142. }
  143. g_string_append_len (out, buffer, nread);
  144. if (nread <= 0) {
  145. out_closed = TRUE;
  146. close (outfd);
  147. }
  148. }
  149. if (!err_closed && FD_ISSET (errfd, &rfds)) {
  150. nread = safe_read (errfd, buffer, 1024, gerror);
  151. if (nread < 0) {
  152. close (errfd);
  153. close (outfd);
  154. return -1;
  155. }
  156. g_string_append_len (err, buffer, nread);
  157. if (nread <= 0) {
  158. err_closed = TRUE;
  159. close (errfd);
  160. }
  161. }
  162. }
  163. } while (res > 0 || (res == -1 && errno == EINTR));
  164. g_free (buffer);
  165. if (out_str)
  166. *out_str = g_string_free (out, FALSE);
  167. if (err_str)
  168. *err_str = g_string_free (err, FALSE);
  169. return 0;
  170. }
  171. static gboolean
  172. create_pipe (int *fds, GError **gerror)
  173. {
  174. if (pipe (fds) == -1) {
  175. set_error ("%s", "Error creating pipe.");
  176. return FALSE;
  177. }
  178. return TRUE;
  179. }
  180. static int
  181. write_all (int fd, const void *vbuf, size_t n)
  182. {
  183. const char *buf = (const char *) vbuf;
  184. size_t nwritten = 0;
  185. int w;
  186. do {
  187. do {
  188. w = write (fd, buf + nwritten, n - nwritten);
  189. } while (w == -1 && errno == EINTR);
  190. if (w == -1)
  191. return -1;
  192. nwritten += w;
  193. } while (nwritten < n);
  194. return nwritten;
  195. }
  196. #endif // HAVE_G_SPAWN
  197. #if !defined(G_OS_WIN32) && defined(HAVE_GETDTABLESIZE)
  198. int
  199. eg_getdtablesize (void)
  200. {
  201. #ifdef HAVE_GETRLIMIT
  202. struct rlimit limit;
  203. int res;
  204. res = getrlimit (RLIMIT_NOFILE, &limit);
  205. g_assert (res == 0);
  206. return limit.rlim_cur;
  207. #else
  208. return getdtablesize ();
  209. #endif
  210. }
  211. #else
  212. int
  213. eg_getdtablesize (void)
  214. {
  215. g_error ("Should not be called");
  216. }
  217. #endif
  218. #if HAVE_G_SPAWN
  219. gboolean
  220. g_spawn_command_line_sync (const gchar *command_line,
  221. gchar **standard_output,
  222. gchar **standard_error,
  223. gint *exit_status,
  224. GError **gerror)
  225. {
  226. pid_t pid;
  227. gchar **argv;
  228. gint argc;
  229. int stdout_pipe [2] = { -1, -1 };
  230. int stderr_pipe [2] = { -1, -1 };
  231. int status;
  232. int res;
  233. if (!g_shell_parse_argv (command_line, &argc, &argv, gerror))
  234. return FALSE;
  235. if (standard_output && !create_pipe (stdout_pipe, gerror))
  236. return FALSE;
  237. if (standard_error && !create_pipe (stderr_pipe, gerror)) {
  238. if (standard_output) {
  239. mono_close_pipe (stdout_pipe);
  240. }
  241. return FALSE;
  242. }
  243. pid = fork ();
  244. if (pid == 0) {
  245. gint i;
  246. if (standard_output) {
  247. close (stdout_pipe [0]);
  248. dup2 (stdout_pipe [1], STDOUT_FILENO);
  249. }
  250. if (standard_error) {
  251. close (stderr_pipe [0]);
  252. dup2 (stderr_pipe [1], STDERR_FILENO);
  253. }
  254. for (i = eg_getdtablesize () - 1; i >= 3; i--)
  255. close (i);
  256. /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */
  257. if (!g_path_is_absolute (argv [0])) {
  258. gchar *arg0;
  259. arg0 = g_find_program_in_path (argv [0]);
  260. if (arg0 == NULL) {
  261. exit (1);
  262. }
  263. //g_free (argv [0]);
  264. argv [0] = arg0;
  265. }
  266. execv (argv [0], argv);
  267. exit (1); /* TODO: What now? */
  268. }
  269. g_strfreev (argv);
  270. if (standard_output)
  271. close (stdout_pipe [1]);
  272. if (standard_error)
  273. close (stderr_pipe [1]);
  274. if (standard_output || standard_error) {
  275. res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, gerror);
  276. if (res) {
  277. waitpid (pid, &status, WNOHANG); /* avoid zombie */
  278. return FALSE;
  279. }
  280. }
  281. NO_INTR (res, waitpid (pid, &status, 0));
  282. /* TODO: What if error? */
  283. if (WIFEXITED (status) && exit_status) {
  284. *exit_status = WEXITSTATUS (status);
  285. }
  286. return TRUE;
  287. }
  288. /*
  289. * This is the only use we have in mono/metadata
  290. !g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, &ch_in, &ch_out, NULL, NULL)
  291. */
  292. gboolean
  293. g_spawn_async_with_pipes (const gchar *working_directory,
  294. gchar **argv,
  295. gchar **envp,
  296. GSpawnFlags flags,
  297. GSpawnChildSetupFunc child_setup,
  298. gpointer user_data,
  299. GPid *child_pid,
  300. gint *standard_input,
  301. gint *standard_output,
  302. gint *standard_error,
  303. GError **gerror)
  304. {
  305. pid_t pid;
  306. int info_pipe [2];
  307. int in_pipe [2] = { -1, -1 };
  308. int out_pipe [2] = { -1, -1 };
  309. int err_pipe [2] = { -1, -1 };
  310. int status;
  311. g_return_val_if_fail (argv != NULL, FALSE); /* Only mandatory arg */
  312. if (!create_pipe (info_pipe, gerror))
  313. return FALSE;
  314. if (standard_output && !create_pipe (out_pipe, gerror)) {
  315. mono_close_pipe (info_pipe);
  316. return FALSE;
  317. }
  318. if (standard_error && !create_pipe (err_pipe, gerror)) {
  319. mono_close_pipe (info_pipe);
  320. mono_close_pipe (out_pipe);
  321. return FALSE;
  322. }
  323. if (standard_input && !create_pipe (in_pipe, gerror)) {
  324. mono_close_pipe (info_pipe);
  325. mono_close_pipe (out_pipe);
  326. mono_close_pipe (err_pipe);
  327. return FALSE;
  328. }
  329. pid = fork ();
  330. if (pid == -1) {
  331. mono_close_pipe (info_pipe);
  332. mono_close_pipe (out_pipe);
  333. mono_close_pipe (err_pipe);
  334. mono_close_pipe (in_pipe);
  335. set_error ("%s", "Error in fork ()");
  336. return FALSE;
  337. }
  338. if (pid == 0) {
  339. /* No zombie left behind */
  340. if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
  341. pid = fork ();
  342. }
  343. if (pid != 0) {
  344. exit (pid == -1 ? 1 : 0);
  345. } else {
  346. gint i;
  347. int fd;
  348. gchar *arg0;
  349. gchar **actual_args;
  350. gint unused;
  351. close (info_pipe [0]);
  352. close (in_pipe [1]);
  353. close (out_pipe [0]);
  354. close (err_pipe [0]);
  355. /* when exec* succeeds, we want to close this fd, which will return
  356. * a 0 read on the parent. We're not supposed to keep it open forever.
  357. * If exec fails, we still can write the error to it before closing.
  358. */
  359. fcntl (info_pipe [1], F_SETFD, FD_CLOEXEC);
  360. if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
  361. pid = getpid ();
  362. NO_INTR (unused, write_all (info_pipe [1], &pid, sizeof (pid_t)));
  363. }
  364. if (working_directory && chdir (working_directory) == -1) {
  365. int err = errno;
  366. NO_INTR (unused, write_all (info_pipe [1], &err, sizeof (int)));
  367. exit (0);
  368. }
  369. if (standard_output) {
  370. dup2 (out_pipe [1], STDOUT_FILENO);
  371. } else if ((flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0) {
  372. fd = open ("/dev/null", O_WRONLY);
  373. dup2 (fd, STDOUT_FILENO);
  374. }
  375. if (standard_error) {
  376. dup2 (err_pipe [1], STDERR_FILENO);
  377. } else if ((flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0) {
  378. fd = open ("/dev/null", O_WRONLY);
  379. dup2 (fd, STDERR_FILENO);
  380. }
  381. if (standard_input) {
  382. dup2 (in_pipe [0], STDIN_FILENO);
  383. } else if ((flags & G_SPAWN_CHILD_INHERITS_STDIN) == 0) {
  384. fd = open ("/dev/null", O_RDONLY);
  385. dup2 (fd, STDIN_FILENO);
  386. }
  387. if ((flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) != 0) {
  388. for (i = eg_getdtablesize () - 1; i >= 3; i--)
  389. close (i);
  390. }
  391. actual_args = ((flags & G_SPAWN_FILE_AND_ARGV_ZERO) == 0) ? argv : argv + 1;
  392. if (envp == NULL)
  393. envp = environ;
  394. if (child_setup)
  395. child_setup (user_data);
  396. arg0 = argv [0];
  397. if (!g_path_is_absolute (arg0) || (flags & G_SPAWN_SEARCH_PATH) != 0) {
  398. arg0 = g_find_program_in_path (argv [0]);
  399. if (arg0 == NULL) {
  400. int err = ENOENT;
  401. write_all (info_pipe [1], &err, sizeof (int));
  402. exit (0);
  403. }
  404. }
  405. execve (arg0, actual_args, envp);
  406. int const err = errno;
  407. write_all (info_pipe [1], &err, sizeof (int));
  408. exit (0);
  409. }
  410. } else if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
  411. int w;
  412. /* Wait for the first child if two are created */
  413. NO_INTR (w, waitpid (pid, &status, 0));
  414. if (status == 1 || w == -1) {
  415. mono_close_pipe (info_pipe);
  416. mono_close_pipe (out_pipe);
  417. mono_close_pipe (err_pipe);
  418. mono_close_pipe (in_pipe);
  419. set_error ("Error in fork (): %d", status);
  420. return FALSE;
  421. }
  422. }
  423. close (info_pipe [1]);
  424. close (in_pipe [0]);
  425. close (out_pipe [1]);
  426. close (err_pipe [1]);
  427. if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
  428. int x;
  429. NO_INTR (x, read (info_pipe [0], &pid, sizeof (pid_t))); /* if we read < sizeof (pid_t)... */
  430. }
  431. if (child_pid) {
  432. *child_pid = pid;
  433. }
  434. if (read (info_pipe [0], &status, sizeof (int)) != 0) {
  435. close (info_pipe [0]);
  436. close (in_pipe [0]);
  437. close (out_pipe [1]);
  438. close (err_pipe [1]);
  439. set_error_status (status, "Error in exec (%d -> %s)", status, strerror (status));
  440. return FALSE;
  441. }
  442. close (info_pipe [0]);
  443. if (standard_input)
  444. *standard_input = in_pipe [1];
  445. if (standard_output)
  446. *standard_output = out_pipe [0];
  447. if (standard_error)
  448. *standard_error = err_pipe [0];
  449. return TRUE;
  450. }
  451. #endif // HAVE_G_SPAWN
  452. #define MONO_EMPTY_SOURCE_FILE(x) extern const char mono_quash_linker_empty_file_warning_ ## x; \
  453. const char mono_quash_linker_empty_file_warning_ ## x = 0;
  454. MONO_EMPTY_SOURCE_FILE (gspawn);