test-spawn.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941
  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "task.h"
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #ifdef _WIN32
  29. # if defined(__MINGW32__)
  30. # include <basetyps.h>
  31. # endif
  32. # include <shellapi.h>
  33. # include <wchar.h>
  34. #else
  35. # include <unistd.h>
  36. # include <sys/wait.h>
  37. #endif
  38. static int close_cb_called;
  39. static int exit_cb_called;
  40. static uv_process_t process;
  41. static uv_timer_t timer;
  42. static uv_process_options_t options;
  43. static char exepath[1024];
  44. static size_t exepath_size = 1024;
  45. static char* args[5];
  46. static int no_term_signal;
  47. #ifndef _WIN32
  48. static int timer_counter;
  49. #endif
  50. static uv_tcp_t tcp_server;
  51. #define OUTPUT_SIZE 1024
  52. static char output[OUTPUT_SIZE];
  53. static int output_used;
  54. static void close_cb(uv_handle_t* handle) {
  55. printf("close_cb\n");
  56. close_cb_called++;
  57. }
  58. static void exit_cb(uv_process_t* process,
  59. int64_t exit_status,
  60. int term_signal) {
  61. printf("exit_cb\n");
  62. exit_cb_called++;
  63. ASSERT(exit_status == 1);
  64. ASSERT(term_signal == 0);
  65. uv_close((uv_handle_t*)process, close_cb);
  66. }
  67. static void fail_cb(uv_process_t* process,
  68. int64_t exit_status,
  69. int term_signal) {
  70. ASSERT(0 && "fail_cb called");
  71. }
  72. static void kill_cb(uv_process_t* process,
  73. int64_t exit_status,
  74. int term_signal) {
  75. int err;
  76. printf("exit_cb\n");
  77. exit_cb_called++;
  78. #ifdef _WIN32
  79. ASSERT(exit_status == 1);
  80. #else
  81. ASSERT(exit_status == 0);
  82. #endif
  83. #if defined(__APPLE__) || defined(__MVS__)
  84. /*
  85. * At least starting with Darwin Kernel Version 16.4.0, sending a SIGTERM to a
  86. * process that is still starting up kills it with SIGKILL instead of SIGTERM.
  87. * See: https://github.com/libuv/libuv/issues/1226
  88. */
  89. ASSERT(no_term_signal || term_signal == SIGTERM || term_signal == SIGKILL);
  90. #else
  91. ASSERT(no_term_signal || term_signal == SIGTERM);
  92. #endif
  93. uv_close((uv_handle_t*)process, close_cb);
  94. /*
  95. * Sending signum == 0 should check if the
  96. * child process is still alive, not kill it.
  97. * This process should be dead.
  98. */
  99. err = uv_kill(process->pid, 0);
  100. ASSERT(err == UV_ESRCH);
  101. }
  102. static void detach_failure_cb(uv_process_t* process,
  103. int64_t exit_status,
  104. int term_signal) {
  105. printf("detach_cb\n");
  106. exit_cb_called++;
  107. }
  108. static void on_alloc(uv_handle_t* handle,
  109. size_t suggested_size,
  110. uv_buf_t* buf) {
  111. buf->base = output + output_used;
  112. buf->len = OUTPUT_SIZE - output_used;
  113. }
  114. static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
  115. if (nread > 0) {
  116. output_used += nread;
  117. } else if (nread < 0) {
  118. ASSERT(nread == UV_EOF);
  119. uv_close((uv_handle_t*)tcp, close_cb);
  120. }
  121. }
  122. #ifndef _WIN32
  123. static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
  124. uv_read_stop(tcp);
  125. on_read(tcp, nread, buf);
  126. }
  127. #endif
  128. static void write_cb(uv_write_t* req, int status) {
  129. ASSERT(status == 0);
  130. uv_close((uv_handle_t*)req->handle, close_cb);
  131. }
  132. static void init_process_options(char* test, uv_exit_cb exit_cb) {
  133. /* Note spawn_helper1 defined in test/run-tests.c */
  134. int r = uv_exepath(exepath, &exepath_size);
  135. ASSERT(r == 0);
  136. exepath[exepath_size] = '\0';
  137. args[0] = exepath;
  138. args[1] = test;
  139. args[2] = NULL;
  140. args[3] = NULL;
  141. args[4] = NULL;
  142. options.file = exepath;
  143. options.args = args;
  144. options.exit_cb = exit_cb;
  145. options.flags = 0;
  146. }
  147. static void timer_cb(uv_timer_t* handle) {
  148. uv_process_kill(&process, /* SIGTERM */ 15);
  149. uv_close((uv_handle_t*)handle, close_cb);
  150. }
  151. #ifndef _WIN32
  152. static void timer_counter_cb(uv_timer_t* handle) {
  153. ++timer_counter;
  154. }
  155. #endif
  156. TEST_IMPL(spawn_fails) {
  157. int r;
  158. init_process_options("", fail_cb);
  159. options.file = options.args[0] = "program-that-had-better-not-exist";
  160. r = uv_spawn(uv_default_loop(), &process, &options);
  161. ASSERT(r == UV_ENOENT || r == UV_EACCES);
  162. ASSERT(0 == uv_is_active((uv_handle_t*) &process));
  163. uv_close((uv_handle_t*) &process, NULL);
  164. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  165. MAKE_VALGRIND_HAPPY();
  166. return 0;
  167. }
  168. #ifndef _WIN32
  169. TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) {
  170. int r;
  171. int status;
  172. int err;
  173. init_process_options("", fail_cb);
  174. options.file = options.args[0] = "program-that-had-better-not-exist";
  175. r = uv_spawn(uv_default_loop(), &process, &options);
  176. ASSERT(r == UV_ENOENT || r == UV_EACCES);
  177. ASSERT(0 == uv_is_active((uv_handle_t*) &process));
  178. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  179. /* verify the child is successfully cleaned up within libuv */
  180. do
  181. err = waitpid(process.pid, &status, 0);
  182. while (err == -1 && errno == EINTR);
  183. ASSERT(err == -1);
  184. ASSERT(errno == ECHILD);
  185. uv_close((uv_handle_t*) &process, NULL);
  186. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  187. MAKE_VALGRIND_HAPPY();
  188. return 0;
  189. }
  190. #endif
  191. TEST_IMPL(spawn_empty_env) {
  192. char* env[1];
  193. /* The autotools dynamic library build requires the presence of
  194. * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH/LIBPATH (other Unices)
  195. * in the environment, but of course that doesn't work with
  196. * the empty environment that we're testing here.
  197. */
  198. if (NULL != getenv("DYLD_LIBRARY_PATH") ||
  199. NULL != getenv("LD_LIBRARY_PATH") ||
  200. NULL != getenv("LIBPATH")) {
  201. RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH/LIBPATH");
  202. }
  203. init_process_options("spawn_helper1", exit_cb);
  204. options.env = env;
  205. env[0] = NULL;
  206. ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
  207. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  208. ASSERT(exit_cb_called == 1);
  209. ASSERT(close_cb_called == 1);
  210. MAKE_VALGRIND_HAPPY();
  211. return 0;
  212. }
  213. TEST_IMPL(spawn_exit_code) {
  214. int r;
  215. init_process_options("spawn_helper1", exit_cb);
  216. r = uv_spawn(uv_default_loop(), &process, &options);
  217. ASSERT(r == 0);
  218. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  219. ASSERT(r == 0);
  220. ASSERT(exit_cb_called == 1);
  221. ASSERT(close_cb_called == 1);
  222. MAKE_VALGRIND_HAPPY();
  223. return 0;
  224. }
  225. TEST_IMPL(spawn_stdout) {
  226. int r;
  227. uv_pipe_t out;
  228. uv_stdio_container_t stdio[2];
  229. init_process_options("spawn_helper2", exit_cb);
  230. uv_pipe_init(uv_default_loop(), &out, 0);
  231. options.stdio = stdio;
  232. options.stdio[0].flags = UV_IGNORE;
  233. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  234. options.stdio[1].data.stream = (uv_stream_t*)&out;
  235. options.stdio_count = 2;
  236. r = uv_spawn(uv_default_loop(), &process, &options);
  237. ASSERT(r == 0);
  238. r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
  239. ASSERT(r == 0);
  240. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  241. ASSERT(r == 0);
  242. ASSERT(exit_cb_called == 1);
  243. ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
  244. printf("output is: %s", output);
  245. ASSERT(strcmp("hello world\n", output) == 0);
  246. MAKE_VALGRIND_HAPPY();
  247. return 0;
  248. }
  249. TEST_IMPL(spawn_stdout_to_file) {
  250. int r;
  251. uv_file file;
  252. uv_fs_t fs_req;
  253. uv_stdio_container_t stdio[2];
  254. uv_buf_t buf;
  255. /* Setup. */
  256. unlink("stdout_file");
  257. init_process_options("spawn_helper2", exit_cb);
  258. r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
  259. S_IRUSR | S_IWUSR, NULL);
  260. ASSERT(r != -1);
  261. uv_fs_req_cleanup(&fs_req);
  262. file = r;
  263. options.stdio = stdio;
  264. options.stdio[0].flags = UV_IGNORE;
  265. options.stdio[1].flags = UV_INHERIT_FD;
  266. options.stdio[1].data.fd = file;
  267. options.stdio_count = 2;
  268. r = uv_spawn(uv_default_loop(), &process, &options);
  269. ASSERT(r == 0);
  270. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  271. ASSERT(r == 0);
  272. ASSERT(exit_cb_called == 1);
  273. ASSERT(close_cb_called == 1);
  274. buf = uv_buf_init(output, sizeof(output));
  275. r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
  276. ASSERT(r == 12);
  277. uv_fs_req_cleanup(&fs_req);
  278. r = uv_fs_close(NULL, &fs_req, file, NULL);
  279. ASSERT(r == 0);
  280. uv_fs_req_cleanup(&fs_req);
  281. printf("output is: %s", output);
  282. ASSERT(strcmp("hello world\n", output) == 0);
  283. /* Cleanup. */
  284. unlink("stdout_file");
  285. MAKE_VALGRIND_HAPPY();
  286. return 0;
  287. }
  288. TEST_IMPL(spawn_stdout_and_stderr_to_file) {
  289. int r;
  290. uv_file file;
  291. uv_fs_t fs_req;
  292. uv_stdio_container_t stdio[3];
  293. uv_buf_t buf;
  294. /* Setup. */
  295. unlink("stdout_file");
  296. init_process_options("spawn_helper6", exit_cb);
  297. r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
  298. S_IRUSR | S_IWUSR, NULL);
  299. ASSERT(r != -1);
  300. uv_fs_req_cleanup(&fs_req);
  301. file = r;
  302. options.stdio = stdio;
  303. options.stdio[0].flags = UV_IGNORE;
  304. options.stdio[1].flags = UV_INHERIT_FD;
  305. options.stdio[1].data.fd = file;
  306. options.stdio[2].flags = UV_INHERIT_FD;
  307. options.stdio[2].data.fd = file;
  308. options.stdio_count = 3;
  309. r = uv_spawn(uv_default_loop(), &process, &options);
  310. ASSERT(r == 0);
  311. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  312. ASSERT(r == 0);
  313. ASSERT(exit_cb_called == 1);
  314. ASSERT(close_cb_called == 1);
  315. buf = uv_buf_init(output, sizeof(output));
  316. r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
  317. ASSERT(r == 27);
  318. uv_fs_req_cleanup(&fs_req);
  319. r = uv_fs_close(NULL, &fs_req, file, NULL);
  320. ASSERT(r == 0);
  321. uv_fs_req_cleanup(&fs_req);
  322. printf("output is: %s", output);
  323. ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);
  324. /* Cleanup. */
  325. unlink("stdout_file");
  326. MAKE_VALGRIND_HAPPY();
  327. return 0;
  328. }
  329. TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
  330. #ifndef _WIN32
  331. int r;
  332. uv_file file;
  333. uv_fs_t fs_req;
  334. uv_stdio_container_t stdio[3];
  335. uv_buf_t buf;
  336. /* Setup. */
  337. unlink("stdout_file");
  338. init_process_options("spawn_helper6", exit_cb);
  339. /* Replace stderr with our file */
  340. r = uv_fs_open(NULL,
  341. &fs_req,
  342. "stdout_file",
  343. O_CREAT | O_RDWR,
  344. S_IRUSR | S_IWUSR,
  345. NULL);
  346. ASSERT(r != -1);
  347. uv_fs_req_cleanup(&fs_req);
  348. file = dup2(r, STDERR_FILENO);
  349. ASSERT(file != -1);
  350. options.stdio = stdio;
  351. options.stdio[0].flags = UV_IGNORE;
  352. options.stdio[1].flags = UV_INHERIT_FD;
  353. options.stdio[1].data.fd = file;
  354. options.stdio[2].flags = UV_INHERIT_FD;
  355. options.stdio[2].data.fd = file;
  356. options.stdio_count = 3;
  357. r = uv_spawn(uv_default_loop(), &process, &options);
  358. ASSERT(r == 0);
  359. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  360. ASSERT(r == 0);
  361. ASSERT(exit_cb_called == 1);
  362. ASSERT(close_cb_called == 1);
  363. buf = uv_buf_init(output, sizeof(output));
  364. r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
  365. ASSERT(r == 27);
  366. uv_fs_req_cleanup(&fs_req);
  367. r = uv_fs_close(NULL, &fs_req, file, NULL);
  368. ASSERT(r == 0);
  369. uv_fs_req_cleanup(&fs_req);
  370. printf("output is: %s", output);
  371. ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);
  372. /* Cleanup. */
  373. unlink("stdout_file");
  374. MAKE_VALGRIND_HAPPY();
  375. return 0;
  376. #else
  377. RETURN_SKIP("Unix only test");
  378. #endif
  379. }
  380. TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
  381. #ifndef _WIN32
  382. int r;
  383. uv_file stdout_file;
  384. uv_file stderr_file;
  385. uv_fs_t fs_req;
  386. uv_stdio_container_t stdio[3];
  387. uv_buf_t buf;
  388. /* Setup. */
  389. unlink("stdout_file");
  390. unlink("stderr_file");
  391. init_process_options("spawn_helper6", exit_cb);
  392. /* open 'stdout_file' and replace STDOUT_FILENO with it */
  393. r = uv_fs_open(NULL,
  394. &fs_req,
  395. "stdout_file",
  396. O_CREAT | O_RDWR,
  397. S_IRUSR | S_IWUSR,
  398. NULL);
  399. ASSERT(r != -1);
  400. uv_fs_req_cleanup(&fs_req);
  401. stdout_file = dup2(r, STDOUT_FILENO);
  402. ASSERT(stdout_file != -1);
  403. /* open 'stderr_file' and replace STDERR_FILENO with it */
  404. r = uv_fs_open(NULL, &fs_req, "stderr_file", O_CREAT | O_RDWR,
  405. S_IRUSR | S_IWUSR, NULL);
  406. ASSERT(r != -1);
  407. uv_fs_req_cleanup(&fs_req);
  408. stderr_file = dup2(r, STDERR_FILENO);
  409. ASSERT(stderr_file != -1);
  410. /* now we're going to swap them: the child process' stdout will be our
  411. * stderr_file and vice versa */
  412. options.stdio = stdio;
  413. options.stdio[0].flags = UV_IGNORE;
  414. options.stdio[1].flags = UV_INHERIT_FD;
  415. options.stdio[1].data.fd = stderr_file;
  416. options.stdio[2].flags = UV_INHERIT_FD;
  417. options.stdio[2].data.fd = stdout_file;
  418. options.stdio_count = 3;
  419. r = uv_spawn(uv_default_loop(), &process, &options);
  420. ASSERT(r == 0);
  421. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  422. ASSERT(r == 0);
  423. ASSERT(exit_cb_called == 1);
  424. ASSERT(close_cb_called == 1);
  425. buf = uv_buf_init(output, sizeof(output));
  426. /* check the content of stdout_file */
  427. r = uv_fs_read(NULL, &fs_req, stdout_file, &buf, 1, 0, NULL);
  428. ASSERT(r >= 15);
  429. uv_fs_req_cleanup(&fs_req);
  430. r = uv_fs_close(NULL, &fs_req, stdout_file, NULL);
  431. ASSERT(r == 0);
  432. uv_fs_req_cleanup(&fs_req);
  433. printf("output is: %s", output);
  434. ASSERT(strncmp("hello errworld\n", output, 15) == 0);
  435. /* check the content of stderr_file */
  436. r = uv_fs_read(NULL, &fs_req, stderr_file, &buf, 1, 0, NULL);
  437. ASSERT(r >= 12);
  438. uv_fs_req_cleanup(&fs_req);
  439. r = uv_fs_close(NULL, &fs_req, stderr_file, NULL);
  440. ASSERT(r == 0);
  441. uv_fs_req_cleanup(&fs_req);
  442. printf("output is: %s", output);
  443. ASSERT(strncmp("hello world\n", output, 12) == 0);
  444. /* Cleanup. */
  445. unlink("stdout_file");
  446. unlink("stderr_file");
  447. MAKE_VALGRIND_HAPPY();
  448. return 0;
  449. #else
  450. RETURN_SKIP("Unix only test");
  451. #endif
  452. }
  453. TEST_IMPL(spawn_stdin) {
  454. int r;
  455. uv_pipe_t out;
  456. uv_pipe_t in;
  457. uv_write_t write_req;
  458. uv_buf_t buf;
  459. uv_stdio_container_t stdio[2];
  460. char buffer[] = "hello-from-spawn_stdin";
  461. init_process_options("spawn_helper3", exit_cb);
  462. uv_pipe_init(uv_default_loop(), &out, 0);
  463. uv_pipe_init(uv_default_loop(), &in, 0);
  464. options.stdio = stdio;
  465. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  466. options.stdio[0].data.stream = (uv_stream_t*)&in;
  467. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  468. options.stdio[1].data.stream = (uv_stream_t*)&out;
  469. options.stdio_count = 2;
  470. r = uv_spawn(uv_default_loop(), &process, &options);
  471. ASSERT(r == 0);
  472. buf.base = buffer;
  473. buf.len = sizeof(buffer);
  474. r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb);
  475. ASSERT(r == 0);
  476. r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
  477. ASSERT(r == 0);
  478. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  479. ASSERT(r == 0);
  480. ASSERT(exit_cb_called == 1);
  481. ASSERT(close_cb_called == 3); /* Once for process twice for the pipe. */
  482. ASSERT(strcmp(buffer, output) == 0);
  483. MAKE_VALGRIND_HAPPY();
  484. return 0;
  485. }
  486. TEST_IMPL(spawn_stdio_greater_than_3) {
  487. int r;
  488. uv_pipe_t pipe;
  489. uv_stdio_container_t stdio[4];
  490. init_process_options("spawn_helper5", exit_cb);
  491. uv_pipe_init(uv_default_loop(), &pipe, 0);
  492. options.stdio = stdio;
  493. options.stdio[0].flags = UV_IGNORE;
  494. options.stdio[1].flags = UV_IGNORE;
  495. options.stdio[2].flags = UV_IGNORE;
  496. options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  497. options.stdio[3].data.stream = (uv_stream_t*)&pipe;
  498. options.stdio_count = 4;
  499. r = uv_spawn(uv_default_loop(), &process, &options);
  500. ASSERT(r == 0);
  501. r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read);
  502. ASSERT(r == 0);
  503. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  504. ASSERT(r == 0);
  505. ASSERT(exit_cb_called == 1);
  506. ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
  507. printf("output from stdio[3] is: %s", output);
  508. ASSERT(strcmp("fourth stdio!\n", output) == 0);
  509. MAKE_VALGRIND_HAPPY();
  510. return 0;
  511. }
  512. int spawn_tcp_server_helper(void) {
  513. uv_tcp_t tcp;
  514. uv_os_sock_t handle;
  515. int r;
  516. r = uv_tcp_init(uv_default_loop(), &tcp);
  517. ASSERT(r == 0);
  518. #ifdef _WIN32
  519. handle = _get_osfhandle(3);
  520. #else
  521. handle = 3;
  522. #endif
  523. r = uv_tcp_open(&tcp, handle);
  524. ASSERT(r == 0);
  525. /* Make sure that we can listen on a socket that was
  526. * passed down from the parent process
  527. */
  528. r = uv_listen((uv_stream_t*)&tcp, SOMAXCONN, NULL);
  529. ASSERT(r == 0);
  530. return 1;
  531. }
  532. TEST_IMPL(spawn_tcp_server) {
  533. uv_stdio_container_t stdio[4];
  534. struct sockaddr_in addr;
  535. int fd;
  536. int r;
  537. #ifdef _WIN32
  538. uv_os_fd_t handle;
  539. #endif
  540. init_process_options("spawn_tcp_server_helper", exit_cb);
  541. ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
  542. fd = -1;
  543. r = uv_tcp_init_ex(uv_default_loop(), &tcp_server, AF_INET);
  544. ASSERT(r == 0);
  545. r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0);
  546. ASSERT(r == 0);
  547. #ifdef _WIN32
  548. r = uv_fileno((uv_handle_t*)&tcp_server, &handle);
  549. fd = _open_osfhandle((intptr_t) handle, 0);
  550. #else
  551. r = uv_fileno((uv_handle_t*)&tcp_server, &fd);
  552. #endif
  553. ASSERT(r == 0);
  554. ASSERT(fd > 0);
  555. options.stdio = stdio;
  556. options.stdio[0].flags = UV_INHERIT_FD;
  557. options.stdio[0].data.fd = 0;
  558. options.stdio[1].flags = UV_INHERIT_FD;
  559. options.stdio[1].data.fd = 1;
  560. options.stdio[2].flags = UV_INHERIT_FD;
  561. options.stdio[2].data.fd = 2;
  562. options.stdio[3].flags = UV_INHERIT_FD;
  563. options.stdio[3].data.fd = fd;
  564. options.stdio_count = 4;
  565. r = uv_spawn(uv_default_loop(), &process, &options);
  566. ASSERT(r == 0);
  567. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  568. ASSERT(r == 0);
  569. ASSERT(exit_cb_called == 1);
  570. ASSERT(close_cb_called == 1);
  571. MAKE_VALGRIND_HAPPY();
  572. return 0;
  573. }
  574. TEST_IMPL(spawn_ignored_stdio) {
  575. int r;
  576. init_process_options("spawn_helper6", exit_cb);
  577. options.stdio = NULL;
  578. options.stdio_count = 0;
  579. r = uv_spawn(uv_default_loop(), &process, &options);
  580. ASSERT(r == 0);
  581. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  582. ASSERT(r == 0);
  583. ASSERT(exit_cb_called == 1);
  584. ASSERT(close_cb_called == 1);
  585. MAKE_VALGRIND_HAPPY();
  586. return 0;
  587. }
  588. TEST_IMPL(spawn_and_kill) {
  589. int r;
  590. init_process_options("spawn_helper4", kill_cb);
  591. r = uv_spawn(uv_default_loop(), &process, &options);
  592. ASSERT(r == 0);
  593. r = uv_timer_init(uv_default_loop(), &timer);
  594. ASSERT(r == 0);
  595. r = uv_timer_start(&timer, timer_cb, 500, 0);
  596. ASSERT(r == 0);
  597. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  598. ASSERT(r == 0);
  599. ASSERT(exit_cb_called == 1);
  600. ASSERT(close_cb_called == 2); /* Once for process and once for timer. */
  601. MAKE_VALGRIND_HAPPY();
  602. return 0;
  603. }
  604. TEST_IMPL(spawn_preserve_env) {
  605. int r;
  606. uv_pipe_t out;
  607. uv_stdio_container_t stdio[2];
  608. init_process_options("spawn_helper7", exit_cb);
  609. uv_pipe_init(uv_default_loop(), &out, 0);
  610. options.stdio = stdio;
  611. options.stdio[0].flags = UV_IGNORE;
  612. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  613. options.stdio[1].data.stream = (uv_stream_t*) &out;
  614. options.stdio_count = 2;
  615. r = putenv("ENV_TEST=testval");
  616. ASSERT(r == 0);
  617. /* Explicitly set options.env to NULL to test for env clobbering. */
  618. options.env = NULL;
  619. r = uv_spawn(uv_default_loop(), &process, &options);
  620. ASSERT(r == 0);
  621. r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
  622. ASSERT(r == 0);
  623. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  624. ASSERT(r == 0);
  625. ASSERT(exit_cb_called == 1);
  626. ASSERT(close_cb_called == 2);
  627. printf("output is: %s", output);
  628. ASSERT(strcmp("testval", output) == 0);
  629. MAKE_VALGRIND_HAPPY();
  630. return 0;
  631. }
  632. TEST_IMPL(spawn_detached) {
  633. int r;
  634. init_process_options("spawn_helper4", detach_failure_cb);
  635. options.flags |= UV_PROCESS_DETACHED;
  636. r = uv_spawn(uv_default_loop(), &process, &options);
  637. ASSERT(r == 0);
  638. uv_unref((uv_handle_t*)&process);
  639. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  640. ASSERT(r == 0);
  641. ASSERT(exit_cb_called == 0);
  642. ASSERT(process.pid == uv_process_get_pid(&process));
  643. r = uv_kill(process.pid, 0);
  644. ASSERT(r == 0);
  645. r = uv_kill(process.pid, 15);
  646. ASSERT(r == 0);
  647. MAKE_VALGRIND_HAPPY();
  648. return 0;
  649. }
  650. TEST_IMPL(spawn_and_kill_with_std) {
  651. int r;
  652. uv_pipe_t in, out, err;
  653. uv_write_t write;
  654. char message[] = "Nancy's joining me because the message this evening is "
  655. "not my message but ours.";
  656. uv_buf_t buf;
  657. uv_stdio_container_t stdio[3];
  658. init_process_options("spawn_helper4", kill_cb);
  659. r = uv_pipe_init(uv_default_loop(), &in, 0);
  660. ASSERT(r == 0);
  661. r = uv_pipe_init(uv_default_loop(), &out, 0);
  662. ASSERT(r == 0);
  663. r = uv_pipe_init(uv_default_loop(), &err, 0);
  664. ASSERT(r == 0);
  665. options.stdio = stdio;
  666. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  667. options.stdio[0].data.stream = (uv_stream_t*)&in;
  668. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  669. options.stdio[1].data.stream = (uv_stream_t*)&out;
  670. options.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  671. options.stdio[2].data.stream = (uv_stream_t*)&err;
  672. options.stdio_count = 3;
  673. r = uv_spawn(uv_default_loop(), &process, &options);
  674. ASSERT(r == 0);
  675. buf = uv_buf_init(message, sizeof message);
  676. r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb);
  677. ASSERT(r == 0);
  678. r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
  679. ASSERT(r == 0);
  680. r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read);
  681. ASSERT(r == 0);
  682. r = uv_timer_init(uv_default_loop(), &timer);
  683. ASSERT(r == 0);
  684. r = uv_timer_start(&timer, timer_cb, 500, 0);
  685. ASSERT(r == 0);
  686. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  687. ASSERT(r == 0);
  688. ASSERT(exit_cb_called == 1);
  689. ASSERT(close_cb_called == 5); /* process x 1, timer x 1, stdio x 3. */
  690. MAKE_VALGRIND_HAPPY();
  691. return 0;
  692. }
  693. TEST_IMPL(spawn_and_ping) {
  694. uv_write_t write_req;
  695. uv_pipe_t in, out;
  696. uv_buf_t buf;
  697. uv_stdio_container_t stdio[2];
  698. int r;
  699. init_process_options("spawn_helper3", exit_cb);
  700. buf = uv_buf_init("TEST", 4);
  701. uv_pipe_init(uv_default_loop(), &out, 0);
  702. uv_pipe_init(uv_default_loop(), &in, 0);
  703. options.stdio = stdio;
  704. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  705. options.stdio[0].data.stream = (uv_stream_t*)&in;
  706. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  707. options.stdio[1].data.stream = (uv_stream_t*)&out;
  708. options.stdio_count = 2;
  709. r = uv_spawn(uv_default_loop(), &process, &options);
  710. ASSERT(r == 0);
  711. /* Sending signum == 0 should check if the
  712. * child process is still alive, not kill it.
  713. */
  714. r = uv_process_kill(&process, 0);
  715. ASSERT(r == 0);
  716. r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb);
  717. ASSERT(r == 0);
  718. r = uv_read_start((uv_stream_t*)&out, on_alloc, on_read);
  719. ASSERT(r == 0);
  720. ASSERT(exit_cb_called == 0);
  721. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  722. ASSERT(r == 0);
  723. ASSERT(exit_cb_called == 1);
  724. ASSERT(strcmp(output, "TEST") == 0);
  725. MAKE_VALGRIND_HAPPY();
  726. return 0;
  727. }
  728. TEST_IMPL(spawn_same_stdout_stderr) {
  729. uv_write_t write_req;
  730. uv_pipe_t in, out;
  731. uv_buf_t buf;
  732. uv_stdio_container_t stdio[3];
  733. int r;
  734. init_process_options("spawn_helper3", exit_cb);
  735. buf = uv_buf_init("TEST", 4);
  736. uv_pipe_init(uv_default_loop(), &out, 0);
  737. uv_pipe_init(uv_default_loop(), &in, 0);
  738. options.stdio = stdio;
  739. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  740. options.stdio[0].data.stream = (uv_stream_t*)&in;
  741. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  742. options.stdio[1].data.stream = (uv_stream_t*)&out;
  743. options.stdio_count = 2;
  744. r = uv_spawn(uv_default_loop(), &process, &options);
  745. ASSERT(r == 0);
  746. /* Sending signum == 0 should check if the
  747. * child process is still alive, not kill it.
  748. */
  749. r = uv_process_kill(&process, 0);
  750. ASSERT(r == 0);
  751. r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb);
  752. ASSERT(r == 0);
  753. r = uv_read_start((uv_stream_t*)&out, on_alloc, on_read);
  754. ASSERT(r == 0);
  755. ASSERT(exit_cb_called == 0);
  756. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  757. ASSERT(r == 0);
  758. ASSERT(exit_cb_called == 1);
  759. ASSERT(strcmp(output, "TEST") == 0);
  760. MAKE_VALGRIND_HAPPY();
  761. return 0;
  762. }
  763. TEST_IMPL(spawn_closed_process_io) {
  764. uv_pipe_t in;
  765. uv_write_t write_req;
  766. uv_buf_t buf;
  767. uv_stdio_container_t stdio[2];
  768. static char buffer[] = "hello-from-spawn_stdin\n";
  769. init_process_options("spawn_helper3", exit_cb);
  770. uv_pipe_init(uv_default_loop(), &in, 0);
  771. options.stdio = stdio;
  772. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  773. options.stdio[0].data.stream = (uv_stream_t*) &in;
  774. options.stdio_count = 1;
  775. close(0); /* Close process stdin. */
  776. ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
  777. buf = uv_buf_init(buffer, sizeof(buffer));
  778. ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
  779. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  780. ASSERT(exit_cb_called == 1);
  781. ASSERT(close_cb_called == 2); /* process, child stdin */
  782. MAKE_VALGRIND_HAPPY();
  783. return 0;
  784. }
  785. TEST_IMPL(kill) {
  786. int r;
  787. #ifdef _WIN32
  788. no_term_signal = 1;
  789. #endif
  790. init_process_options("spawn_helper4", kill_cb);
  791. /* Verify that uv_spawn() resets the signal disposition. */
  792. #ifndef _WIN32
  793. {
  794. sigset_t set;
  795. sigemptyset(&set);
  796. sigaddset(&set, SIGTERM);
  797. ASSERT(0 == pthread_sigmask(SIG_BLOCK, &set, NULL));
  798. }
  799. ASSERT(SIG_ERR != signal(SIGTERM, SIG_IGN));
  800. #endif
  801. r = uv_spawn(uv_default_loop(), &process, &options);
  802. ASSERT(r == 0);
  803. #ifndef _WIN32
  804. {
  805. sigset_t set;
  806. sigemptyset(&set);
  807. sigaddset(&set, SIGTERM);
  808. ASSERT(0 == pthread_sigmask(SIG_UNBLOCK, &set, NULL));
  809. }
  810. ASSERT(SIG_ERR != signal(SIGTERM, SIG_DFL));
  811. #endif
  812. /* Sending signum == 0 should check if the
  813. * child process is still alive, not kill it.
  814. */
  815. r = uv_kill(process.pid, 0);
  816. ASSERT(r == 0);
  817. /* Kill the process. */
  818. r = uv_kill(process.pid, /* SIGTERM */ 15);
  819. ASSERT(r == 0);
  820. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  821. ASSERT(r == 0);
  822. ASSERT(exit_cb_called == 1);
  823. ASSERT(close_cb_called == 1);
  824. MAKE_VALGRIND_HAPPY();
  825. return 0;
  826. }
  827. #ifdef _WIN32
  828. TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
  829. int r;
  830. uv_pipe_t out;
  831. char name[64];
  832. HANDLE pipe_handle;
  833. uv_stdio_container_t stdio[2];
  834. init_process_options("spawn_helper2", exit_cb);
  835. uv_pipe_init(uv_default_loop(), &out, 0);
  836. options.stdio = stdio;
  837. options.stdio[0].flags = UV_IGNORE;
  838. options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
  839. options.stdio[1].data.stream = (uv_stream_t*)&out;
  840. options.stdio_count = 2;
  841. /* Create a pipe that'll cause a collision. */
  842. snprintf(name,
  843. sizeof(name),
  844. "\\\\.\\pipe\\uv\\%p-%d",
  845. &out,
  846. GetCurrentProcessId());
  847. pipe_handle = CreateNamedPipeA(name,
  848. PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
  849. PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
  850. 10,
  851. 65536,
  852. 65536,
  853. 0,
  854. NULL);
  855. ASSERT(pipe_handle != INVALID_HANDLE_VALUE);
  856. r = uv_spawn(uv_default_loop(), &process, &options);
  857. ASSERT(r == 0);
  858. r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read);
  859. ASSERT(r == 0);
  860. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  861. ASSERT(r == 0);
  862. ASSERT(exit_cb_called == 1);
  863. ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */
  864. printf("output is: %s", output);
  865. ASSERT(strcmp("hello world\n", output) == 0);
  866. MAKE_VALGRIND_HAPPY();
  867. return 0;
  868. }
  869. #if !defined(USING_UV_SHARED)
  870. int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr);
  871. WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target);
  872. TEST_IMPL(argument_escaping) {
  873. const WCHAR* test_str[] = {
  874. L"",
  875. L"HelloWorld",
  876. L"Hello World",
  877. L"Hello\"World",
  878. L"Hello World\\",
  879. L"Hello\\\"World",
  880. L"Hello\\World",
  881. L"Hello\\\\World",
  882. L"Hello World\\",
  883. L"c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\""
  884. };
  885. const int count = sizeof(test_str) / sizeof(*test_str);
  886. WCHAR** test_output;
  887. WCHAR* command_line;
  888. WCHAR** cracked;
  889. size_t total_size = 0;
  890. int i;
  891. int num_args;
  892. int result;
  893. char* verbatim[] = {
  894. "cmd.exe",
  895. "/c",
  896. "c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"",
  897. NULL
  898. };
  899. WCHAR* verbatim_output;
  900. WCHAR* non_verbatim_output;
  901. test_output = calloc(count, sizeof(WCHAR*));
  902. ASSERT(test_output != NULL);
  903. for (i = 0; i < count; ++i) {
  904. test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR));
  905. quote_cmd_arg(test_str[i], test_output[i]);
  906. wprintf(L"input : %s\n", test_str[i]);
  907. wprintf(L"output: %s\n", test_output[i]);
  908. total_size += wcslen(test_output[i]) + 1;
  909. }
  910. command_line = calloc(total_size + 1, sizeof(WCHAR));
  911. ASSERT(command_line != NULL);
  912. for (i = 0; i < count; ++i) {
  913. wcscat(command_line, test_output[i]);
  914. wcscat(command_line, L" ");
  915. }
  916. command_line[total_size - 1] = L'\0';
  917. wprintf(L"command_line: %s\n", command_line);
  918. cracked = CommandLineToArgvW(command_line, &num_args);
  919. for (i = 0; i < num_args; ++i) {
  920. wprintf(L"%d: %s\t%s\n", i, test_str[i], cracked[i]);
  921. ASSERT(wcscmp(test_str[i], cracked[i]) == 0);
  922. }
  923. LocalFree(cracked);
  924. for (i = 0; i < count; ++i) {
  925. free(test_output[i]);
  926. }
  927. free(test_output);
  928. result = make_program_args(verbatim, 1, &verbatim_output);
  929. ASSERT(result == 0);
  930. result = make_program_args(verbatim, 0, &non_verbatim_output);
  931. ASSERT(result == 0);
  932. wprintf(L" verbatim_output: %s\n", verbatim_output);
  933. wprintf(L"non_verbatim_output: %s\n", non_verbatim_output);
  934. ASSERT(wcscmp(verbatim_output,
  935. L"cmd.exe /c c:\\path\\to\\node.exe --eval "
  936. L"\"require('c:\\\\path\\\\to\\\\test.js')\"") == 0);
  937. ASSERT(wcscmp(non_verbatim_output,
  938. L"cmd.exe /c \"c:\\path\\to\\node.exe --eval "
  939. L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0);
  940. free(verbatim_output);
  941. free(non_verbatim_output);
  942. return 0;
  943. }
  944. int make_program_env(char** env_block, WCHAR** dst_ptr);
  945. TEST_IMPL(environment_creation) {
  946. size_t i;
  947. char* environment[] = {
  948. "FOO=BAR",
  949. "SYSTEM=ROOT", /* substring of a supplied var name */
  950. "SYSTEMROOTED=OMG", /* supplied var name is a substring */
  951. "TEMP=C:\\Temp",
  952. "INVALID",
  953. "BAZ=QUX",
  954. "B_Z=QUX",
  955. "B\xe2\x82\xacZ=QUX",
  956. "B\xf0\x90\x80\x82Z=QUX",
  957. "B\xef\xbd\xa1Z=QUX",
  958. "B\xf0\xa3\x91\x96Z=QUX",
  959. "BAZ", /* repeat, invalid variable */
  960. NULL
  961. };
  962. WCHAR* wenvironment[] = {
  963. L"BAZ=QUX",
  964. L"B_Z=QUX",
  965. L"B\x20acZ=QUX",
  966. L"B\xd800\xdc02Z=QUX",
  967. L"B\xd84d\xdc56Z=QUX",
  968. L"B\xff61Z=QUX",
  969. L"FOO=BAR",
  970. L"SYSTEM=ROOT", /* substring of a supplied var name */
  971. L"SYSTEMROOTED=OMG", /* supplied var name is a substring */
  972. L"TEMP=C:\\Temp",
  973. };
  974. WCHAR* from_env[] = {
  975. /* list should be kept in sync with list
  976. * in process.c, minus variables in wenvironment */
  977. L"HOMEDRIVE",
  978. L"HOMEPATH",
  979. L"LOGONSERVER",
  980. L"PATH",
  981. L"USERDOMAIN",
  982. L"USERNAME",
  983. L"USERPROFILE",
  984. L"SYSTEMDRIVE",
  985. L"SYSTEMROOT",
  986. L"WINDIR",
  987. /* test for behavior in the absence of a
  988. * required-environment variable: */
  989. L"ZTHIS_ENV_VARIABLE_DOES_NOT_EXIST",
  990. };
  991. int found_in_loc_env[ARRAY_SIZE(wenvironment)] = {0};
  992. int found_in_usr_env[ARRAY_SIZE(from_env)] = {0};
  993. WCHAR *expected[ARRAY_SIZE(from_env)];
  994. int result;
  995. WCHAR* str;
  996. WCHAR* prev;
  997. WCHAR* env;
  998. for (i = 0; i < ARRAY_SIZE(from_env); i++) {
  999. /* copy expected additions to environment locally */
  1000. size_t len = GetEnvironmentVariableW(from_env[i], NULL, 0);
  1001. if (len == 0) {
  1002. found_in_usr_env[i] = 1;
  1003. str = malloc(1 * sizeof(WCHAR));
  1004. *str = 0;
  1005. expected[i] = str;
  1006. } else {
  1007. size_t name_len = wcslen(from_env[i]);
  1008. str = malloc((name_len+1+len) * sizeof(WCHAR));
  1009. wmemcpy(str, from_env[i], name_len);
  1010. expected[i] = str;
  1011. str += name_len;
  1012. *str++ = L'=';
  1013. GetEnvironmentVariableW(from_env[i], str, len);
  1014. }
  1015. }
  1016. result = make_program_env(environment, &env);
  1017. ASSERT(result == 0);
  1018. for (str = env, prev = NULL; *str; prev = str, str += wcslen(str) + 1) {
  1019. int found = 0;
  1020. #if 0
  1021. _cputws(str);
  1022. putchar('\n');
  1023. #endif
  1024. for (i = 0; i < ARRAY_SIZE(wenvironment) && !found; i++) {
  1025. if (!wcscmp(str, wenvironment[i])) {
  1026. ASSERT(!found_in_loc_env[i]);
  1027. found_in_loc_env[i] = 1;
  1028. found = 1;
  1029. }
  1030. }
  1031. for (i = 0; i < ARRAY_SIZE(expected) && !found; i++) {
  1032. if (!wcscmp(str, expected[i])) {
  1033. ASSERT(!found_in_usr_env[i]);
  1034. found_in_usr_env[i] = 1;
  1035. found = 1;
  1036. }
  1037. }
  1038. if (prev) { /* verify sort order -- requires Vista */
  1039. #if _WIN32_WINNT >= 0x0600 && \
  1040. (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
  1041. ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1);
  1042. #endif
  1043. }
  1044. ASSERT(found); /* verify that we expected this variable */
  1045. }
  1046. /* verify that we found all expected variables */
  1047. for (i = 0; i < ARRAY_SIZE(wenvironment); i++) {
  1048. ASSERT(found_in_loc_env[i]);
  1049. }
  1050. for (i = 0; i < ARRAY_SIZE(expected); i++) {
  1051. ASSERT(found_in_usr_env[i]);
  1052. }
  1053. return 0;
  1054. }
  1055. #endif
  1056. /* Regression test for issue #909 */
  1057. TEST_IMPL(spawn_with_an_odd_path) {
  1058. int r;
  1059. char newpath[2048];
  1060. char *path = getenv("PATH");
  1061. ASSERT(path != NULL);
  1062. snprintf(newpath, 2048, ";.;%s", path);
  1063. SetEnvironmentVariable("PATH", newpath);
  1064. init_process_options("", exit_cb);
  1065. options.file = options.args[0] = "program-that-had-better-not-exist";
  1066. r = uv_spawn(uv_default_loop(), &process, &options);
  1067. ASSERT(r == UV_ENOENT || r == UV_EACCES);
  1068. ASSERT(0 == uv_is_active((uv_handle_t*) &process));
  1069. uv_close((uv_handle_t*) &process, NULL);
  1070. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  1071. MAKE_VALGRIND_HAPPY();
  1072. return 0;
  1073. }
  1074. #endif
  1075. #ifndef _WIN32
  1076. TEST_IMPL(spawn_setuid_setgid) {
  1077. int r;
  1078. struct passwd* pw;
  1079. char uidstr[10];
  1080. char gidstr[10];
  1081. /* if not root, then this will fail. */
  1082. uv_uid_t uid = getuid();
  1083. if (uid != 0) {
  1084. RETURN_SKIP("It should be run as root user");
  1085. }
  1086. init_process_options("spawn_helper_setuid_setgid", exit_cb);
  1087. /* become the "nobody" user. */
  1088. pw = getpwnam("nobody");
  1089. ASSERT(pw != NULL);
  1090. options.uid = pw->pw_uid;
  1091. options.gid = pw->pw_gid;
  1092. snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
  1093. snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid);
  1094. options.args[2] = uidstr;
  1095. options.args[3] = gidstr;
  1096. options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
  1097. r = uv_spawn(uv_default_loop(), &process, &options);
  1098. if (r == UV_EACCES)
  1099. RETURN_SKIP("user 'nobody' cannot access the test runner");
  1100. ASSERT(r == 0);
  1101. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1102. ASSERT(r == 0);
  1103. ASSERT(exit_cb_called == 1);
  1104. ASSERT(close_cb_called == 1);
  1105. MAKE_VALGRIND_HAPPY();
  1106. return 0;
  1107. }
  1108. #endif
  1109. #ifndef _WIN32
  1110. TEST_IMPL(spawn_setuid_fails) {
  1111. int r;
  1112. /* if root, become nobody. */
  1113. /* On IBMi PASE, there is no nobody user. */
  1114. #ifndef __PASE__
  1115. uv_uid_t uid = getuid();
  1116. if (uid == 0) {
  1117. struct passwd* pw;
  1118. pw = getpwnam("nobody");
  1119. ASSERT(pw != NULL);
  1120. ASSERT(0 == setgid(pw->pw_gid));
  1121. ASSERT(0 == setuid(pw->pw_uid));
  1122. }
  1123. #endif /* !__PASE__ */
  1124. init_process_options("spawn_helper1", fail_cb);
  1125. options.flags |= UV_PROCESS_SETUID;
  1126. /* On IBMi PASE, there is no root user. User may grant
  1127. * root-like privileges, including setting uid to 0.
  1128. */
  1129. #if defined(__PASE__)
  1130. options.uid = -1;
  1131. #else
  1132. options.uid = 0;
  1133. #endif
  1134. /* These flags should be ignored on Unices. */
  1135. options.flags |= UV_PROCESS_WINDOWS_HIDE;
  1136. options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE;
  1137. options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI;
  1138. options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
  1139. r = uv_spawn(uv_default_loop(), &process, &options);
  1140. #if defined(__CYGWIN__) || defined(__PASE__)
  1141. ASSERT(r == UV_EINVAL);
  1142. #else
  1143. ASSERT(r == UV_EPERM);
  1144. #endif
  1145. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1146. ASSERT(r == 0);
  1147. ASSERT(close_cb_called == 0);
  1148. MAKE_VALGRIND_HAPPY();
  1149. return 0;
  1150. }
  1151. TEST_IMPL(spawn_setgid_fails) {
  1152. int r;
  1153. /* if root, become nobody. */
  1154. /* On IBMi PASE, there is no nobody user. */
  1155. #ifndef __PASE__
  1156. uv_uid_t uid = getuid();
  1157. if (uid == 0) {
  1158. struct passwd* pw;
  1159. pw = getpwnam("nobody");
  1160. ASSERT(pw != NULL);
  1161. ASSERT(0 == setgid(pw->pw_gid));
  1162. ASSERT(0 == setuid(pw->pw_uid));
  1163. }
  1164. #endif /* !__PASE__ */
  1165. init_process_options("spawn_helper1", fail_cb);
  1166. options.flags |= UV_PROCESS_SETGID;
  1167. /* On IBMi PASE, there is no root user. User may grant
  1168. * root-like privileges, including setting gid to 0.
  1169. */
  1170. #if defined(__MVS__) || defined(__PASE__)
  1171. options.gid = -1;
  1172. #else
  1173. options.gid = 0;
  1174. #endif
  1175. r = uv_spawn(uv_default_loop(), &process, &options);
  1176. #if defined(__CYGWIN__) || defined(__MVS__) || defined(__PASE__)
  1177. ASSERT(r == UV_EINVAL);
  1178. #else
  1179. ASSERT(r == UV_EPERM);
  1180. #endif
  1181. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1182. ASSERT(r == 0);
  1183. ASSERT(close_cb_called == 0);
  1184. MAKE_VALGRIND_HAPPY();
  1185. return 0;
  1186. }
  1187. #endif
  1188. #ifdef _WIN32
  1189. static void exit_cb_unexpected(uv_process_t* process,
  1190. int64_t exit_status,
  1191. int term_signal) {
  1192. ASSERT(0 && "should not have been called");
  1193. }
  1194. TEST_IMPL(spawn_setuid_fails) {
  1195. int r;
  1196. init_process_options("spawn_helper1", exit_cb_unexpected);
  1197. options.flags |= UV_PROCESS_SETUID;
  1198. options.uid = (uv_uid_t) -42424242;
  1199. r = uv_spawn(uv_default_loop(), &process, &options);
  1200. ASSERT(r == UV_ENOTSUP);
  1201. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1202. ASSERT(r == 0);
  1203. ASSERT(close_cb_called == 0);
  1204. MAKE_VALGRIND_HAPPY();
  1205. return 0;
  1206. }
  1207. TEST_IMPL(spawn_setgid_fails) {
  1208. int r;
  1209. init_process_options("spawn_helper1", exit_cb_unexpected);
  1210. options.flags |= UV_PROCESS_SETGID;
  1211. options.gid = (uv_gid_t) -42424242;
  1212. r = uv_spawn(uv_default_loop(), &process, &options);
  1213. ASSERT(r == UV_ENOTSUP);
  1214. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1215. ASSERT(r == 0);
  1216. ASSERT(close_cb_called == 0);
  1217. MAKE_VALGRIND_HAPPY();
  1218. return 0;
  1219. }
  1220. #endif
  1221. TEST_IMPL(spawn_auto_unref) {
  1222. init_process_options("spawn_helper1", NULL);
  1223. ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
  1224. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  1225. ASSERT(0 == uv_is_closing((uv_handle_t*) &process));
  1226. uv_close((uv_handle_t*) &process, NULL);
  1227. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  1228. ASSERT(1 == uv_is_closing((uv_handle_t*) &process));
  1229. MAKE_VALGRIND_HAPPY();
  1230. return 0;
  1231. }
  1232. #ifndef _WIN32
  1233. TEST_IMPL(spawn_fs_open) {
  1234. int fd;
  1235. uv_fs_t fs_req;
  1236. uv_pipe_t in;
  1237. uv_write_t write_req;
  1238. uv_buf_t buf;
  1239. uv_stdio_container_t stdio[1];
  1240. fd = uv_fs_open(NULL, &fs_req, "/dev/null", O_RDWR, 0, NULL);
  1241. ASSERT(fd >= 0);
  1242. uv_fs_req_cleanup(&fs_req);
  1243. init_process_options("spawn_helper8", exit_cb);
  1244. ASSERT(0 == uv_pipe_init(uv_default_loop(), &in, 0));
  1245. options.stdio = stdio;
  1246. options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
  1247. options.stdio[0].data.stream = (uv_stream_t*) &in;
  1248. options.stdio_count = 1;
  1249. ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
  1250. buf = uv_buf_init((char*) &fd, sizeof(fd));
  1251. ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
  1252. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
  1253. ASSERT(0 == uv_fs_close(NULL, &fs_req, fd, NULL));
  1254. ASSERT(exit_cb_called == 1);
  1255. ASSERT(close_cb_called == 2); /* One for `in`, one for process */
  1256. MAKE_VALGRIND_HAPPY();
  1257. return 0;
  1258. }
  1259. #endif /* !_WIN32 */
  1260. #ifndef _WIN32
  1261. TEST_IMPL(closed_fd_events) {
  1262. uv_stdio_container_t stdio[3];
  1263. uv_pipe_t pipe_handle;
  1264. int fd[2];
  1265. /* create a pipe and share it with a child process */
  1266. ASSERT(0 == pipe(fd));
  1267. /* spawn_helper4 blocks indefinitely. */
  1268. init_process_options("spawn_helper4", exit_cb);
  1269. options.stdio_count = 3;
  1270. options.stdio = stdio;
  1271. options.stdio[0].flags = UV_INHERIT_FD;
  1272. options.stdio[0].data.fd = fd[0];
  1273. options.stdio[1].flags = UV_IGNORE;
  1274. options.stdio[2].flags = UV_IGNORE;
  1275. ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
  1276. uv_unref((uv_handle_t*) &process);
  1277. /* read from the pipe with uv */
  1278. ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
  1279. ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0]));
  1280. fd[0] = -1;
  1281. ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once));
  1282. ASSERT(1 == write(fd[1], "", 1));
  1283. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
  1284. /* should have received just one byte */
  1285. ASSERT(output_used == 1);
  1286. /* close the pipe and see if we still get events */
  1287. uv_close((uv_handle_t*) &pipe_handle, close_cb);
  1288. ASSERT(1 == write(fd[1], "", 1));
  1289. ASSERT(0 == uv_timer_init(uv_default_loop(), &timer));
  1290. ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0));
  1291. /* see if any spurious events interrupt the timer */
  1292. if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE))
  1293. /* have to run again to really trigger the timer */
  1294. ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
  1295. ASSERT(timer_counter == 1);
  1296. /* cleanup */
  1297. ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15));
  1298. ASSERT(0 == close(fd[1]));
  1299. MAKE_VALGRIND_HAPPY();
  1300. return 0;
  1301. }
  1302. #endif /* !_WIN32 */
  1303. TEST_IMPL(spawn_reads_child_path) {
  1304. int r;
  1305. int len;
  1306. char file[64];
  1307. char path[1024];
  1308. char* env[3];
  1309. /* Need to carry over the dynamic linker path when the test runner is
  1310. * linked against libuv.so, see https://github.com/libuv/libuv/issues/85.
  1311. */
  1312. #if defined(__APPLE__)
  1313. static const char dyld_path_var[] = "DYLD_LIBRARY_PATH";
  1314. #elif defined __MVS__
  1315. static const char dyld_path_var[] = "LIBPATH";
  1316. #else
  1317. static const char dyld_path_var[] = "LD_LIBRARY_PATH";
  1318. #endif
  1319. /* Set up the process, but make sure that the file to run is relative and
  1320. * requires a lookup into PATH. */
  1321. init_process_options("spawn_helper1", exit_cb);
  1322. /* Set up the PATH env variable */
  1323. for (len = strlen(exepath);
  1324. exepath[len - 1] != '/' && exepath[len - 1] != '\\';
  1325. len--);
  1326. strcpy(file, exepath + len);
  1327. exepath[len] = 0;
  1328. strcpy(path, "PATH=");
  1329. strcpy(path + 5, exepath);
  1330. #if defined(__CYGWIN__) || defined(__MSYS__)
  1331. /* Carry over the dynamic linker path in case the test runner
  1332. is linked against cyguv-1.dll or msys-uv-1.dll, see above. */
  1333. {
  1334. char* syspath = getenv("PATH");
  1335. if (syspath != NULL) {
  1336. strcat(path, ":");
  1337. strcat(path, syspath);
  1338. }
  1339. }
  1340. #endif
  1341. env[0] = path;
  1342. env[1] = getenv(dyld_path_var);
  1343. env[2] = NULL;
  1344. if (env[1] != NULL) {
  1345. static char buf[1024 + sizeof(dyld_path_var)];
  1346. snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]);
  1347. env[1] = buf;
  1348. }
  1349. options.file = file;
  1350. options.args[0] = file;
  1351. options.env = env;
  1352. r = uv_spawn(uv_default_loop(), &process, &options);
  1353. ASSERT(r == 0);
  1354. r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
  1355. ASSERT(r == 0);
  1356. ASSERT(exit_cb_called == 1);
  1357. ASSERT(close_cb_called == 1);
  1358. MAKE_VALGRIND_HAPPY();
  1359. return 0;
  1360. }
  1361. #ifndef _WIN32
  1362. static int mpipe(int *fds) {
  1363. if (pipe(fds) == -1)
  1364. return -1;
  1365. if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
  1366. fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
  1367. close(fds[0]);
  1368. close(fds[1]);
  1369. return -1;
  1370. }
  1371. return 0;
  1372. }
  1373. #else
  1374. static int mpipe(int *fds) {
  1375. SECURITY_ATTRIBUTES attr;
  1376. HANDLE readh, writeh;
  1377. attr.nLength = sizeof(attr);
  1378. attr.lpSecurityDescriptor = NULL;
  1379. attr.bInheritHandle = FALSE;
  1380. if (!CreatePipe(&readh, &writeh, &attr, 0))
  1381. return -1;
  1382. fds[0] = _open_osfhandle((intptr_t)readh, 0);
  1383. fds[1] = _open_osfhandle((intptr_t)writeh, 0);
  1384. if (fds[0] == -1 || fds[1] == -1) {
  1385. CloseHandle(readh);
  1386. CloseHandle(writeh);
  1387. return -1;
  1388. }
  1389. return 0;
  1390. }
  1391. #endif /* !_WIN32 */
  1392. TEST_IMPL(spawn_inherit_streams) {
  1393. uv_process_t child_req;
  1394. uv_stdio_container_t child_stdio[2];
  1395. int fds_stdin[2];
  1396. int fds_stdout[2];
  1397. uv_pipe_t pipe_stdin_child;
  1398. uv_pipe_t pipe_stdout_child;
  1399. uv_pipe_t pipe_stdin_parent;
  1400. uv_pipe_t pipe_stdout_parent;
  1401. unsigned char ubuf[OUTPUT_SIZE - 1];
  1402. uv_buf_t buf;
  1403. unsigned int i;
  1404. int r;
  1405. int bidir;
  1406. uv_write_t write_req;
  1407. uv_loop_t* loop;
  1408. init_process_options("spawn_helper9", exit_cb);
  1409. loop = uv_default_loop();
  1410. ASSERT(uv_pipe_init(loop, &pipe_stdin_child, 0) == 0);
  1411. ASSERT(uv_pipe_init(loop, &pipe_stdout_child, 0) == 0);
  1412. ASSERT(uv_pipe_init(loop, &pipe_stdin_parent, 0) == 0);
  1413. ASSERT(uv_pipe_init(loop, &pipe_stdout_parent, 0) == 0);
  1414. ASSERT(mpipe(fds_stdin) != -1);
  1415. ASSERT(mpipe(fds_stdout) != -1);
  1416. ASSERT(uv_pipe_open(&pipe_stdin_child, fds_stdin[0]) == 0);
  1417. ASSERT(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]) == 0);
  1418. ASSERT(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1]) == 0);
  1419. ASSERT(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0]) == 0);
  1420. ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_child));
  1421. ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_child));
  1422. ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdin_parent));
  1423. ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_parent));
  1424. /* Some systems (SVR4) open a bidirectional pipe, most don't. */
  1425. bidir = uv_is_writable((uv_stream_t*) &pipe_stdin_child);
  1426. ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_child) == bidir);
  1427. ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_parent) == bidir);
  1428. ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_parent) == bidir);
  1429. child_stdio[0].flags = UV_INHERIT_STREAM;
  1430. child_stdio[0].data.stream = (uv_stream_t *)&pipe_stdin_child;
  1431. child_stdio[1].flags = UV_INHERIT_STREAM;
  1432. child_stdio[1].data.stream = (uv_stream_t *)&pipe_stdout_child;
  1433. options.stdio = child_stdio;
  1434. options.stdio_count = 2;
  1435. ASSERT(uv_spawn(loop, &child_req, &options) == 0);
  1436. uv_close((uv_handle_t*)&pipe_stdin_child, NULL);
  1437. uv_close((uv_handle_t*)&pipe_stdout_child, NULL);
  1438. buf = uv_buf_init((char*)ubuf, sizeof ubuf);
  1439. for (i = 0; i < sizeof ubuf; ++i)
  1440. ubuf[i] = i & 255u;
  1441. memset(output, 0, sizeof ubuf);
  1442. r = uv_write(&write_req,
  1443. (uv_stream_t*)&pipe_stdin_parent,
  1444. &buf,
  1445. 1,
  1446. write_cb);
  1447. ASSERT(r == 0);
  1448. r = uv_read_start((uv_stream_t*)&pipe_stdout_parent, on_alloc, on_read);
  1449. ASSERT(r == 0);
  1450. r = uv_run(loop, UV_RUN_DEFAULT);
  1451. ASSERT(r == 0);
  1452. ASSERT(exit_cb_called == 1);
  1453. ASSERT(close_cb_called == 3);
  1454. r = memcmp(ubuf, output, sizeof ubuf);
  1455. ASSERT(r == 0);
  1456. MAKE_VALGRIND_HAPPY();
  1457. return 0;
  1458. }
  1459. TEST_IMPL(spawn_quoted_path) {
  1460. #ifndef _WIN32
  1461. RETURN_SKIP("Test for Windows");
  1462. #else
  1463. char* quoted_path_env[2];
  1464. args[0] = "not_existing";
  1465. args[1] = NULL;
  1466. options.file = args[0];
  1467. options.args = args;
  1468. options.exit_cb = exit_cb;
  1469. options.flags = 0;
  1470. /* We test if search_path works correctly with semicolons in quoted path. We
  1471. * will use an invalid drive, so we are sure no executable is spawned. */
  1472. quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other";
  1473. quoted_path_env[1] = NULL;
  1474. options.env = quoted_path_env;
  1475. /* We test if libuv will not segfault. */
  1476. uv_spawn(uv_default_loop(), &process, &options);
  1477. MAKE_VALGRIND_HAPPY();
  1478. return 0;
  1479. #endif
  1480. }
  1481. /* Helper for child process of spawn_inherit_streams */
  1482. #ifndef _WIN32
  1483. void spawn_stdin_stdout(void) {
  1484. char buf[1024];
  1485. char* pbuf;
  1486. for (;;) {
  1487. ssize_t r, w, c;
  1488. do {
  1489. r = read(0, buf, sizeof buf);
  1490. } while (r == -1 && errno == EINTR);
  1491. if (r == 0) {
  1492. return;
  1493. }
  1494. ASSERT(r > 0);
  1495. c = r;
  1496. pbuf = buf;
  1497. while (c) {
  1498. do {
  1499. w = write(1, pbuf, (size_t)c);
  1500. } while (w == -1 && errno == EINTR);
  1501. ASSERT(w >= 0);
  1502. pbuf = pbuf + w;
  1503. c = c - w;
  1504. }
  1505. }
  1506. }
  1507. #else
  1508. void spawn_stdin_stdout(void) {
  1509. char buf[1024];
  1510. char* pbuf;
  1511. HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
  1512. HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
  1513. ASSERT(h_stdin != INVALID_HANDLE_VALUE);
  1514. ASSERT(h_stdout != INVALID_HANDLE_VALUE);
  1515. for (;;) {
  1516. DWORD n_read;
  1517. DWORD n_written;
  1518. DWORD to_write;
  1519. if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
  1520. ASSERT(GetLastError() == ERROR_BROKEN_PIPE);
  1521. return;
  1522. }
  1523. to_write = n_read;
  1524. pbuf = buf;
  1525. while (to_write) {
  1526. ASSERT(WriteFile(h_stdout, pbuf, to_write, &n_written, NULL));
  1527. to_write -= n_written;
  1528. pbuf += n_written;
  1529. }
  1530. }
  1531. }
  1532. #endif /* !_WIN32 */