1 2 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 * IN THE SOFTWARE. 21 */ 22 23 #include "uv.h" 24 #include "task.h" 25 #include <errno.h> 26 #include <fcntl.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #ifdef _WIN32 32 # include <shellapi.h> 33 # include <wchar.h> 34 typedef BOOL (WINAPI *sCompareObjectHandles)(_In_ HANDLE, _In_ HANDLE); 35 # define unlink _unlink 36 # define putenv _putenv 37 # define close _close 38 #else 39 # include <unistd.h> 40 # include <sys/wait.h> 41 #endif 42 43 44 static int close_cb_called; 45 static int exit_cb_called; 46 static uv_process_t process; 47 static uv_timer_t timer; 48 static uv_process_options_t options; 49 static char exepath[1024]; 50 static size_t exepath_size = 1024; 51 static char* args[5]; 52 static int no_term_signal; 53 static int timer_counter; 54 static uv_tcp_t tcp_server; 55 56 #define OUTPUT_SIZE 1024 57 static char output[OUTPUT_SIZE]; 58 static int output_used; 59 60 61 static void close_cb(uv_handle_t* handle) { 62 printf("close_cb\n"); 63 close_cb_called++; 64 } 65 66 static void exit_cb(uv_process_t* process, 67 int64_t exit_status, 68 int term_signal) { 69 printf("exit_cb\n"); 70 exit_cb_called++; 71 ASSERT_EQ(1, exit_status); 72 ASSERT_OK(term_signal); 73 uv_close((uv_handle_t*) process, close_cb); 74 } 75 76 77 static void fail_cb(uv_process_t* process, 78 int64_t exit_status, 79 int term_signal) { 80 ASSERT(0 && "fail_cb called"); 81 } 82 83 84 static void kill_cb(uv_process_t* process, 85 int64_t exit_status, 86 int term_signal) { 87 int err; 88 89 printf("exit_cb\n"); 90 exit_cb_called++; 91 #ifdef _WIN32 92 ASSERT_EQ(1, exit_status); 93 #else 94 ASSERT_OK(exit_status); 95 #endif 96 #if defined(__APPLE__) || defined(__MVS__) 97 /* 98 * At least starting with Darwin Kernel Version 16.4.0, sending a SIGTERM to a 99 * process that is still starting up kills it with SIGKILL instead of SIGTERM. 100 * See: https://github.com/libuv/libuv/issues/1226 101 */ 102 ASSERT(no_term_signal || term_signal == SIGTERM || term_signal == SIGKILL); 103 #else 104 ASSERT(no_term_signal || term_signal == SIGTERM); 105 #endif 106 uv_close((uv_handle_t*) process, close_cb); 107 108 /* 109 * Sending signum == 0 should check if the 110 * child process is still alive, not kill it. 111 * This process should be dead. 112 */ 113 err = uv_kill(process->pid, 0); 114 ASSERT_EQ(err, UV_ESRCH); 115 } 116 117 static void detach_failure_cb(uv_process_t* process, 118 int64_t exit_status, 119 int term_signal) { 120 printf("detach_cb\n"); 121 exit_cb_called++; 122 } 123 124 static void on_alloc(uv_handle_t* handle, 125 size_t suggested_size, 126 uv_buf_t* buf) { 127 buf->base = output + output_used; 128 buf->len = OUTPUT_SIZE - output_used; 129 } 130 131 132 static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { 133 if (nread > 0) { 134 output_used += nread; 135 } else if (nread < 0) { 136 ASSERT_EQ(nread, UV_EOF); 137 uv_close((uv_handle_t*) tcp, close_cb); 138 } 139 } 140 141 142 static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { 143 uv_read_stop(tcp); 144 on_read(tcp, nread, buf); 145 } 146 147 148 static void write_cb(uv_write_t* req, int status) { 149 ASSERT_OK(status); 150 uv_close((uv_handle_t*) req->handle, close_cb); 151 } 152 153 154 static void write_null_cb(uv_write_t* req, int status) { 155 ASSERT_OK(status); 156 } 157 158 159 static void init_process_options(char* test, uv_exit_cb exit_cb) { 160 /* Note spawn_helper1 defined in test/run-tests.c */ 161 int r = uv_exepath(exepath, &exepath_size); 162 ASSERT_OK(r); 163 exepath[exepath_size] = '\0'; 164 args[0] = exepath; 165 args[1] = test; 166 args[2] = NULL; 167 args[3] = NULL; 168 args[4] = NULL; 169 options.file = exepath; 170 options.args = args; 171 options.exit_cb = exit_cb; 172 options.flags = 0; 173 } 174 175 176 static void timer_cb(uv_timer_t* handle) { 177 uv_process_kill(&process, SIGTERM); 178 uv_close((uv_handle_t*) handle, close_cb); 179 } 180 181 182 static void timer_counter_cb(uv_timer_t* handle) { 183 ++timer_counter; 184 } 185 186 187 TEST_IMPL(spawn_fails) { 188 int r; 189 190 init_process_options("", fail_cb); 191 options.file = options.args[0] = "program-that-had-better-not-exist"; 192 193 r = uv_spawn(uv_default_loop(), &process, &options); 194 ASSERT(r == UV_ENOENT || r == UV_EACCES); 195 ASSERT_OK(uv_is_active((uv_handle_t*) &process)); 196 uv_close((uv_handle_t*) &process, NULL); 197 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 198 199 MAKE_VALGRIND_HAPPY(uv_default_loop()); 200 return 0; 201 } 202 203 204 #ifndef _WIN32 205 TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) { 206 int r; 207 int status; 208 int err; 209 210 init_process_options("", fail_cb); 211 options.file = options.args[0] = "program-that-had-better-not-exist"; 212 213 r = uv_spawn(uv_default_loop(), &process, &options); 214 ASSERT(r == UV_ENOENT || r == UV_EACCES); 215 ASSERT_OK(uv_is_active((uv_handle_t*) &process)); 216 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 217 218 /* verify the child is successfully cleaned up within libuv */ 219 do 220 err = waitpid(process.pid, &status, 0); 221 while (err == -1 && errno == EINTR); 222 223 ASSERT_EQ(err, -1); 224 ASSERT_EQ(errno, ECHILD); 225 226 uv_close((uv_handle_t*) &process, NULL); 227 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 228 229 MAKE_VALGRIND_HAPPY(uv_default_loop()); 230 return 0; 231 } 232 #endif 233 234 235 TEST_IMPL(spawn_empty_env) { 236 char* env[1]; 237 238 /* The autotools dynamic library build requires the presence of 239 * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH/LIBPATH (other Unices) 240 * in the environment, but of course that doesn't work with 241 * the empty environment that we're testing here. 242 */ 243 if (NULL != getenv("DYLD_LIBRARY_PATH") || 244 NULL != getenv("LD_LIBRARY_PATH") || 245 NULL != getenv("LIBPATH")) { 246 RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH/LIBPATH"); 247 } 248 249 init_process_options("spawn_helper1", exit_cb); 250 options.env = env; 251 env[0] = NULL; 252 253 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 254 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 255 256 ASSERT_EQ(1, exit_cb_called); 257 ASSERT_EQ(1, close_cb_called); 258 259 MAKE_VALGRIND_HAPPY(uv_default_loop()); 260 return 0; 261 } 262 263 264 TEST_IMPL(spawn_exit_code) { 265 int r; 266 267 init_process_options("spawn_helper1", exit_cb); 268 269 r = uv_spawn(uv_default_loop(), &process, &options); 270 ASSERT_OK(r); 271 272 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 273 ASSERT_OK(r); 274 275 ASSERT_EQ(1, exit_cb_called); 276 ASSERT_EQ(1, close_cb_called); 277 278 MAKE_VALGRIND_HAPPY(uv_default_loop()); 279 return 0; 280 } 281 282 283 TEST_IMPL(spawn_stdout) { 284 int r; 285 uv_pipe_t out; 286 uv_stdio_container_t stdio[2]; 287 288 init_process_options("spawn_helper2", exit_cb); 289 290 uv_pipe_init(uv_default_loop(), &out, 0); 291 options.stdio = stdio; 292 options.stdio[0].flags = UV_IGNORE; 293 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 294 options.stdio[1].data.stream = (uv_stream_t*) &out; 295 options.stdio_count = 2; 296 297 r = uv_spawn(uv_default_loop(), &process, &options); 298 ASSERT_OK(r); 299 300 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 301 ASSERT_OK(r); 302 303 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 304 ASSERT_OK(r); 305 306 ASSERT_EQ(1, exit_cb_called); 307 ASSERT_EQ(2, close_cb_called); /* Once for process once for the pipe. */ 308 printf("output is: %s", output); 309 ASSERT_OK(strcmp("hello world\n", output)); 310 311 MAKE_VALGRIND_HAPPY(uv_default_loop()); 312 return 0; 313 } 314 315 316 TEST_IMPL(spawn_stdout_to_file) { 317 int r; 318 uv_file file; 319 uv_fs_t fs_req; 320 uv_stdio_container_t stdio[2]; 321 uv_buf_t buf; 322 323 /* Setup. */ 324 unlink("stdout_file"); 325 326 init_process_options("spawn_helper2", exit_cb); 327 328 r = uv_fs_open(NULL, &fs_req, "stdout_file", UV_FS_O_CREAT | UV_FS_O_RDWR, 329 S_IRUSR | S_IWUSR, NULL); 330 ASSERT_NE(r, -1); 331 uv_fs_req_cleanup(&fs_req); 332 333 file = r; 334 335 options.stdio = stdio; 336 options.stdio[0].flags = UV_IGNORE; 337 options.stdio[1].flags = UV_INHERIT_FD; 338 options.stdio[1].data.fd = file; 339 options.stdio_count = 2; 340 341 r = uv_spawn(uv_default_loop(), &process, &options); 342 ASSERT_OK(r); 343 344 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 345 ASSERT_OK(r); 346 347 ASSERT_EQ(1, exit_cb_called); 348 ASSERT_EQ(1, close_cb_called); 349 350 buf = uv_buf_init(output, sizeof(output)); 351 r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL); 352 ASSERT_EQ(12, r); 353 uv_fs_req_cleanup(&fs_req); 354 355 r = uv_fs_close(NULL, &fs_req, file, NULL); 356 ASSERT_OK(r); 357 uv_fs_req_cleanup(&fs_req); 358 359 printf("output is: %s", output); 360 ASSERT_OK(strcmp("hello world\n", output)); 361 362 /* Cleanup. */ 363 unlink("stdout_file"); 364 365 MAKE_VALGRIND_HAPPY(uv_default_loop()); 366 return 0; 367 } 368 369 370 TEST_IMPL(spawn_stdout_and_stderr_to_file) { 371 int r; 372 uv_file file; 373 uv_fs_t fs_req; 374 uv_stdio_container_t stdio[3]; 375 uv_buf_t buf; 376 377 /* Setup. */ 378 unlink("stdout_file"); 379 380 init_process_options("spawn_helper6", exit_cb); 381 382 r = uv_fs_open(NULL, &fs_req, "stdout_file", UV_FS_O_CREAT | UV_FS_O_RDWR, 383 S_IRUSR | S_IWUSR, NULL); 384 ASSERT_NE(r, -1); 385 uv_fs_req_cleanup(&fs_req); 386 387 file = r; 388 389 options.stdio = stdio; 390 options.stdio[0].flags = UV_IGNORE; 391 options.stdio[1].flags = UV_INHERIT_FD; 392 options.stdio[1].data.fd = file; 393 options.stdio[2].flags = UV_INHERIT_FD; 394 options.stdio[2].data.fd = file; 395 options.stdio_count = 3; 396 397 r = uv_spawn(uv_default_loop(), &process, &options); 398 ASSERT_OK(r); 399 400 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 401 ASSERT_OK(r); 402 403 ASSERT_EQ(1, exit_cb_called); 404 ASSERT_EQ(1, close_cb_called); 405 406 buf = uv_buf_init(output, sizeof(output)); 407 r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL); 408 ASSERT_EQ(27, r); 409 uv_fs_req_cleanup(&fs_req); 410 411 r = uv_fs_close(NULL, &fs_req, file, NULL); 412 ASSERT_OK(r); 413 uv_fs_req_cleanup(&fs_req); 414 415 printf("output is: %s", output); 416 ASSERT_OK(strcmp("hello world\nhello errworld\n", output)); 417 418 /* Cleanup. */ 419 unlink("stdout_file"); 420 421 MAKE_VALGRIND_HAPPY(uv_default_loop()); 422 return 0; 423 } 424 425 426 TEST_IMPL(spawn_stdout_and_stderr_to_file2) { 427 #ifndef _WIN32 428 int r; 429 uv_file file; 430 uv_fs_t fs_req; 431 uv_stdio_container_t stdio[3]; 432 uv_buf_t buf; 433 434 /* Setup. */ 435 unlink("stdout_file"); 436 437 init_process_options("spawn_helper6", exit_cb); 438 439 /* Replace stderr with our file */ 440 r = uv_fs_open(NULL, 441 &fs_req, 442 "stdout_file", 443 O_CREAT | O_RDWR, 444 S_IRUSR | S_IWUSR, 445 NULL); 446 ASSERT_NE(r, -1); 447 uv_fs_req_cleanup(&fs_req); 448 file = dup2(r, STDERR_FILENO); 449 ASSERT_NE(file, -1); 450 451 options.stdio = stdio; 452 options.stdio[0].flags = UV_IGNORE; 453 options.stdio[1].flags = UV_INHERIT_FD; 454 options.stdio[1].data.fd = file; 455 options.stdio[2].flags = UV_INHERIT_FD; 456 options.stdio[2].data.fd = file; 457 options.stdio_count = 3; 458 459 r = uv_spawn(uv_default_loop(), &process, &options); 460 ASSERT_OK(r); 461 462 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 463 ASSERT_OK(r); 464 465 ASSERT_EQ(1, exit_cb_called); 466 ASSERT_EQ(1, close_cb_called); 467 468 buf = uv_buf_init(output, sizeof(output)); 469 r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL); 470 ASSERT_EQ(27, r); 471 uv_fs_req_cleanup(&fs_req); 472 473 r = uv_fs_close(NULL, &fs_req, file, NULL); 474 ASSERT_OK(r); 475 uv_fs_req_cleanup(&fs_req); 476 477 printf("output is: %s", output); 478 ASSERT_OK(strcmp("hello world\nhello errworld\n", output)); 479 480 /* Cleanup. */ 481 unlink("stdout_file"); 482 483 MAKE_VALGRIND_HAPPY(uv_default_loop()); 484 return 0; 485 #else 486 RETURN_SKIP("Unix only test"); 487 #endif 488 } 489 490 491 TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) { 492 #ifndef _WIN32 493 int r; 494 uv_file stdout_file; 495 uv_file stderr_file; 496 uv_fs_t fs_req; 497 uv_stdio_container_t stdio[3]; 498 uv_buf_t buf; 499 500 /* Setup. */ 501 unlink("stdout_file"); 502 unlink("stderr_file"); 503 504 init_process_options("spawn_helper6", exit_cb); 505 506 /* open 'stdout_file' and replace STDOUT_FILENO with it */ 507 r = uv_fs_open(NULL, 508 &fs_req, 509 "stdout_file", 510 O_CREAT | O_RDWR, 511 S_IRUSR | S_IWUSR, 512 NULL); 513 ASSERT_NE(r, -1); 514 uv_fs_req_cleanup(&fs_req); 515 stdout_file = dup2(r, STDOUT_FILENO); 516 ASSERT_NE(stdout_file, -1); 517 518 /* open 'stderr_file' and replace STDERR_FILENO with it */ 519 r = uv_fs_open(NULL, &fs_req, "stderr_file", O_CREAT | O_RDWR, 520 S_IRUSR | S_IWUSR, NULL); 521 ASSERT_NE(r, -1); 522 uv_fs_req_cleanup(&fs_req); 523 stderr_file = dup2(r, STDERR_FILENO); 524 ASSERT_NE(stderr_file, -1); 525 526 /* now we're going to swap them: the child process' stdout will be our 527 * stderr_file and vice versa */ 528 options.stdio = stdio; 529 options.stdio[0].flags = UV_IGNORE; 530 options.stdio[1].flags = UV_INHERIT_FD; 531 options.stdio[1].data.fd = stderr_file; 532 options.stdio[2].flags = UV_INHERIT_FD; 533 options.stdio[2].data.fd = stdout_file; 534 options.stdio_count = 3; 535 536 r = uv_spawn(uv_default_loop(), &process, &options); 537 ASSERT_OK(r); 538 539 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 540 ASSERT_OK(r); 541 542 ASSERT_EQ(1, exit_cb_called); 543 ASSERT_EQ(1, close_cb_called); 544 545 buf = uv_buf_init(output, sizeof(output)); 546 547 /* check the content of stdout_file */ 548 r = uv_fs_read(NULL, &fs_req, stdout_file, &buf, 1, 0, NULL); 549 ASSERT_GE(r, 15); 550 uv_fs_req_cleanup(&fs_req); 551 552 r = uv_fs_close(NULL, &fs_req, stdout_file, NULL); 553 ASSERT_OK(r); 554 uv_fs_req_cleanup(&fs_req); 555 556 printf("output is: %s", output); 557 ASSERT_OK(strncmp("hello errworld\n", output, 15)); 558 559 /* check the content of stderr_file */ 560 r = uv_fs_read(NULL, &fs_req, stderr_file, &buf, 1, 0, NULL); 561 ASSERT_GE(r, 12); 562 uv_fs_req_cleanup(&fs_req); 563 564 r = uv_fs_close(NULL, &fs_req, stderr_file, NULL); 565 ASSERT_OK(r); 566 uv_fs_req_cleanup(&fs_req); 567 568 printf("output is: %s", output); 569 ASSERT_OK(strncmp("hello world\n", output, 12)); 570 571 /* Cleanup. */ 572 unlink("stdout_file"); 573 unlink("stderr_file"); 574 575 MAKE_VALGRIND_HAPPY(uv_default_loop()); 576 return 0; 577 #else 578 RETURN_SKIP("Unix only test"); 579 #endif 580 } 581 582 583 TEST_IMPL(spawn_stdin) { 584 int r; 585 uv_pipe_t out; 586 uv_pipe_t in; 587 uv_write_t write_req; 588 uv_buf_t buf; 589 uv_stdio_container_t stdio[2]; 590 char buffer[] = "hello-from-spawn_stdin"; 591 592 init_process_options("spawn_helper3", exit_cb); 593 594 uv_pipe_init(uv_default_loop(), &out, 0); 595 uv_pipe_init(uv_default_loop(), &in, 0); 596 options.stdio = stdio; 597 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 598 options.stdio[0].data.stream = (uv_stream_t*) ∈ 599 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 600 options.stdio[1].data.stream = (uv_stream_t*) &out; 601 options.stdio_count = 2; 602 603 r = uv_spawn(uv_default_loop(), &process, &options); 604 ASSERT_OK(r); 605 606 buf.base = buffer; 607 buf.len = sizeof(buffer); 608 r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb); 609 ASSERT_OK(r); 610 611 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 612 ASSERT_OK(r); 613 614 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 615 ASSERT_OK(r); 616 617 ASSERT_EQ(1, exit_cb_called); 618 ASSERT_EQ(3, close_cb_called); /* Once for process twice for the pipe. */ 619 ASSERT_OK(strcmp(buffer, output)); 620 621 MAKE_VALGRIND_HAPPY(uv_default_loop()); 622 return 0; 623 } 624 625 626 TEST_IMPL(spawn_stdio_greater_than_3) { 627 int r; 628 uv_pipe_t pipe; 629 uv_stdio_container_t stdio[4]; 630 631 init_process_options("spawn_helper5", exit_cb); 632 633 uv_pipe_init(uv_default_loop(), &pipe, 0); 634 options.stdio = stdio; 635 options.stdio[0].flags = UV_IGNORE; 636 options.stdio[1].flags = UV_IGNORE; 637 options.stdio[2].flags = UV_IGNORE; 638 options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 639 options.stdio[3].data.stream = (uv_stream_t*) &pipe; 640 options.stdio_count = 4; 641 642 r = uv_spawn(uv_default_loop(), &process, &options); 643 ASSERT_OK(r); 644 645 r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read); 646 ASSERT_OK(r); 647 648 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 649 ASSERT_OK(r); 650 651 ASSERT_EQ(1, exit_cb_called); 652 ASSERT_EQ(2, close_cb_called); /* Once for process once for the pipe. */ 653 printf("output from stdio[3] is: %s", output); 654 ASSERT_OK(strcmp("fourth stdio!\n", output)); 655 656 MAKE_VALGRIND_HAPPY(uv_default_loop()); 657 return 0; 658 } 659 660 661 int spawn_tcp_server_helper(void) { 662 uv_tcp_t tcp; 663 uv_os_sock_t handle; 664 int r; 665 666 r = uv_tcp_init(uv_default_loop(), &tcp); 667 ASSERT_OK(r); 668 669 #ifdef _WIN32 670 handle = _get_osfhandle(3); 671 #else 672 handle = 3; 673 #endif 674 r = uv_tcp_open(&tcp, handle); 675 ASSERT_OK(r); 676 677 /* Make sure that we can listen on a socket that was 678 * passed down from the parent process 679 */ 680 r = uv_listen((uv_stream_t*) &tcp, SOMAXCONN, NULL); 681 ASSERT_OK(r); 682 683 return 1; 684 } 685 686 687 TEST_IMPL(spawn_tcp_server) { 688 uv_stdio_container_t stdio[4]; 689 struct sockaddr_in addr; 690 int fd; 691 int r; 692 #ifdef _WIN32 693 uv_os_fd_t handle; 694 #endif 695 696 init_process_options("spawn_tcp_server_helper", exit_cb); 697 698 ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 699 700 fd = -1; 701 r = uv_tcp_init_ex(uv_default_loop(), &tcp_server, AF_INET); 702 ASSERT_OK(r); 703 r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); 704 ASSERT_OK(r); 705 #ifdef _WIN32 706 r = uv_fileno((uv_handle_t*) &tcp_server, &handle); 707 fd = _open_osfhandle((intptr_t) handle, 0); 708 #else 709 r = uv_fileno((uv_handle_t*) &tcp_server, &fd); 710 #endif 711 ASSERT_OK(r); 712 ASSERT_GT(fd, 0); 713 714 options.stdio = stdio; 715 options.stdio[0].flags = UV_INHERIT_FD; 716 options.stdio[0].data.fd = 0; 717 options.stdio[1].flags = UV_INHERIT_FD; 718 options.stdio[1].data.fd = 1; 719 options.stdio[2].flags = UV_INHERIT_FD; 720 options.stdio[2].data.fd = 2; 721 options.stdio[3].flags = UV_INHERIT_FD; 722 options.stdio[3].data.fd = fd; 723 options.stdio_count = 4; 724 725 r = uv_spawn(uv_default_loop(), &process, &options); 726 ASSERT_OK(r); 727 728 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 729 ASSERT_OK(r); 730 731 ASSERT_EQ(1, exit_cb_called); 732 ASSERT_EQ(1, close_cb_called); 733 734 MAKE_VALGRIND_HAPPY(uv_default_loop()); 735 return 0; 736 } 737 738 739 TEST_IMPL(spawn_ignored_stdio) { 740 int r; 741 742 init_process_options("spawn_helper6", exit_cb); 743 744 options.stdio = NULL; 745 options.stdio_count = 0; 746 747 r = uv_spawn(uv_default_loop(), &process, &options); 748 ASSERT_OK(r); 749 750 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 751 ASSERT_OK(r); 752 753 ASSERT_EQ(1, exit_cb_called); 754 ASSERT_EQ(1, close_cb_called); 755 756 MAKE_VALGRIND_HAPPY(uv_default_loop()); 757 return 0; 758 } 759 760 761 TEST_IMPL(spawn_and_kill) { 762 int r; 763 764 init_process_options("spawn_helper4", kill_cb); 765 766 r = uv_spawn(uv_default_loop(), &process, &options); 767 ASSERT_OK(r); 768 769 r = uv_timer_init(uv_default_loop(), &timer); 770 ASSERT_OK(r); 771 772 r = uv_timer_start(&timer, timer_cb, 500, 0); 773 ASSERT_OK(r); 774 775 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 776 ASSERT_OK(r); 777 778 ASSERT_EQ(1, exit_cb_called); 779 ASSERT_EQ(2, close_cb_called); /* Once for process and once for timer. */ 780 781 MAKE_VALGRIND_HAPPY(uv_default_loop()); 782 return 0; 783 } 784 785 786 TEST_IMPL(spawn_preserve_env) { 787 int r; 788 uv_pipe_t out; 789 uv_stdio_container_t stdio[2]; 790 791 init_process_options("spawn_helper7", exit_cb); 792 793 uv_pipe_init(uv_default_loop(), &out, 0); 794 options.stdio = stdio; 795 options.stdio[0].flags = UV_IGNORE; 796 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 797 options.stdio[1].data.stream = (uv_stream_t*) &out; 798 options.stdio_count = 2; 799 800 r = putenv("ENV_TEST=testval"); 801 ASSERT_OK(r); 802 803 /* Explicitly set options.env to NULL to test for env clobbering. */ 804 options.env = NULL; 805 806 r = uv_spawn(uv_default_loop(), &process, &options); 807 ASSERT_OK(r); 808 809 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 810 ASSERT_OK(r); 811 812 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 813 ASSERT_OK(r); 814 815 ASSERT_EQ(1, exit_cb_called); 816 ASSERT_EQ(2, close_cb_called); 817 818 printf("output is: %s", output); 819 ASSERT_OK(strcmp("testval", output)); 820 821 MAKE_VALGRIND_HAPPY(uv_default_loop()); 822 return 0; 823 } 824 825 826 TEST_IMPL(spawn_detached) { 827 int r; 828 829 init_process_options("spawn_helper4", detach_failure_cb); 830 831 options.flags |= UV_PROCESS_DETACHED; 832 833 r = uv_spawn(uv_default_loop(), &process, &options); 834 ASSERT_OK(r); 835 836 uv_unref((uv_handle_t*) &process); 837 838 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 839 ASSERT_OK(r); 840 841 ASSERT_OK(exit_cb_called); 842 843 ASSERT_EQ(process.pid, uv_process_get_pid(&process)); 844 845 r = uv_kill(process.pid, 0); 846 ASSERT_OK(r); 847 848 r = uv_kill(process.pid, SIGTERM); 849 ASSERT_OK(r); 850 851 MAKE_VALGRIND_HAPPY(uv_default_loop()); 852 return 0; 853 } 854 855 TEST_IMPL(spawn_and_kill_with_std) { 856 int r; 857 uv_pipe_t in, out, err; 858 uv_write_t write; 859 char message[] = "Nancy's joining me because the message this evening is " 860 "not my message but ours."; 861 uv_buf_t buf; 862 uv_stdio_container_t stdio[3]; 863 864 init_process_options("spawn_helper4", kill_cb); 865 866 r = uv_pipe_init(uv_default_loop(), &in, 0); 867 ASSERT_OK(r); 868 869 r = uv_pipe_init(uv_default_loop(), &out, 0); 870 ASSERT_OK(r); 871 872 r = uv_pipe_init(uv_default_loop(), &err, 0); 873 ASSERT_OK(r); 874 875 options.stdio = stdio; 876 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 877 options.stdio[0].data.stream = (uv_stream_t*) ∈ 878 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 879 options.stdio[1].data.stream = (uv_stream_t*) &out; 880 options.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 881 options.stdio[2].data.stream = (uv_stream_t*) &err; 882 options.stdio_count = 3; 883 884 r = uv_spawn(uv_default_loop(), &process, &options); 885 ASSERT_OK(r); 886 887 buf = uv_buf_init(message, sizeof message); 888 r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb); 889 ASSERT_OK(r); 890 891 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 892 ASSERT_OK(r); 893 894 r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read); 895 ASSERT_OK(r); 896 897 r = uv_timer_init(uv_default_loop(), &timer); 898 ASSERT_OK(r); 899 900 r = uv_timer_start(&timer, timer_cb, 500, 0); 901 ASSERT_OK(r); 902 903 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 904 ASSERT_OK(r); 905 906 ASSERT_EQ(1, exit_cb_called); 907 ASSERT_EQ(5, close_cb_called); /* process x 1, timer x 1, stdio x 3. */ 908 909 MAKE_VALGRIND_HAPPY(uv_default_loop()); 910 return 0; 911 } 912 913 914 TEST_IMPL(spawn_and_ping) { 915 uv_write_t write_req; 916 uv_pipe_t in, out; 917 uv_buf_t buf; 918 uv_stdio_container_t stdio[2]; 919 int r; 920 921 init_process_options("spawn_helper3", exit_cb); 922 buf = uv_buf_init("TEST", 4); 923 924 uv_pipe_init(uv_default_loop(), &out, 0); 925 uv_pipe_init(uv_default_loop(), &in, 0); 926 options.stdio = stdio; 927 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 928 options.stdio[0].data.stream = (uv_stream_t*) ∈ 929 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 930 options.stdio[1].data.stream = (uv_stream_t*) &out; 931 options.stdio_count = 2; 932 933 r = uv_spawn(uv_default_loop(), &process, &options); 934 ASSERT_OK(r); 935 936 /* Sending signum == 0 should check if the 937 * child process is still alive, not kill it. 938 */ 939 r = uv_process_kill(&process, 0); 940 ASSERT_OK(r); 941 942 r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb); 943 ASSERT_OK(r); 944 945 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 946 ASSERT_OK(r); 947 948 ASSERT_OK(exit_cb_called); 949 950 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 951 ASSERT_OK(r); 952 953 ASSERT_EQ(1, exit_cb_called); 954 ASSERT_OK(strcmp(output, "TEST")); 955 956 MAKE_VALGRIND_HAPPY(uv_default_loop()); 957 return 0; 958 } 959 960 961 TEST_IMPL(spawn_same_stdout_stderr) { 962 uv_write_t write_req; 963 uv_pipe_t in, out; 964 uv_buf_t buf; 965 uv_stdio_container_t stdio[3]; 966 int r; 967 968 init_process_options("spawn_helper3", exit_cb); 969 buf = uv_buf_init("TEST", 4); 970 971 uv_pipe_init(uv_default_loop(), &out, 0); 972 uv_pipe_init(uv_default_loop(), &in, 0); 973 options.stdio = stdio; 974 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 975 options.stdio[0].data.stream = (uv_stream_t*) ∈ 976 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 977 options.stdio[1].data.stream = (uv_stream_t*) &out; 978 options.stdio_count = 2; 979 980 r = uv_spawn(uv_default_loop(), &process, &options); 981 ASSERT_OK(r); 982 983 /* Sending signum == 0 should check if the 984 * child process is still alive, not kill it. 985 */ 986 r = uv_process_kill(&process, 0); 987 ASSERT_OK(r); 988 989 r = uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb); 990 ASSERT_OK(r); 991 992 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 993 ASSERT_OK(r); 994 995 ASSERT_OK(exit_cb_called); 996 997 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 998 ASSERT_OK(r); 999 1000 ASSERT_EQ(1, exit_cb_called); 1001 ASSERT_OK(strcmp(output, "TEST")); 1002 1003 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1004 return 0; 1005 } 1006 1007 1008 TEST_IMPL(spawn_closed_process_io) { 1009 uv_pipe_t in; 1010 uv_write_t write_req; 1011 uv_buf_t buf; 1012 uv_stdio_container_t stdio[2]; 1013 static char buffer[] = "hello-from-spawn_stdin\n"; 1014 1015 init_process_options("spawn_helper3", exit_cb); 1016 1017 uv_pipe_init(uv_default_loop(), &in, 0); 1018 options.stdio = stdio; 1019 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 1020 options.stdio[0].data.stream = (uv_stream_t*) ∈ 1021 options.stdio_count = 1; 1022 1023 close(0); /* Close process stdin. */ 1024 1025 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1026 1027 buf = uv_buf_init(buffer, sizeof(buffer)); 1028 ASSERT_OK(uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb)); 1029 1030 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1031 1032 ASSERT_EQ(1, exit_cb_called); 1033 ASSERT_EQ(2, close_cb_called); /* process, child stdin */ 1034 1035 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1036 return 0; 1037 } 1038 1039 1040 TEST_IMPL(kill) { 1041 int r; 1042 1043 #ifdef _WIN32 1044 no_term_signal = 1; 1045 #endif 1046 1047 init_process_options("spawn_helper4", kill_cb); 1048 1049 /* Verify that uv_spawn() resets the signal disposition. */ 1050 #ifndef _WIN32 1051 { 1052 sigset_t set; 1053 sigemptyset(&set); 1054 sigaddset(&set, SIGTERM); 1055 ASSERT_OK(pthread_sigmask(SIG_BLOCK, &set, NULL)); 1056 } 1057 ASSERT_PTR_NE(SIG_ERR, signal(SIGTERM, SIG_IGN)); 1058 #endif 1059 1060 r = uv_spawn(uv_default_loop(), &process, &options); 1061 ASSERT_OK(r); 1062 1063 #ifndef _WIN32 1064 { 1065 sigset_t set; 1066 sigemptyset(&set); 1067 sigaddset(&set, SIGTERM); 1068 ASSERT_OK(pthread_sigmask(SIG_UNBLOCK, &set, NULL)); 1069 } 1070 ASSERT_PTR_NE(SIG_ERR, signal(SIGTERM, SIG_DFL)); 1071 #endif 1072 1073 /* Sending signum == 0 should check if the 1074 * child process is still alive, not kill it. 1075 */ 1076 r = uv_kill(process.pid, 0); 1077 ASSERT_OK(r); 1078 1079 /* Kill the process. */ 1080 r = uv_kill(process.pid, SIGTERM); 1081 ASSERT_OK(r); 1082 1083 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1084 ASSERT_OK(r); 1085 1086 ASSERT_EQ(1, exit_cb_called); 1087 ASSERT_EQ(1, close_cb_called); 1088 1089 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1090 return 0; 1091 } 1092 1093 1094 #ifdef _WIN32 1095 TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { 1096 int r; 1097 uv_pipe_t out; 1098 char name[64]; 1099 HANDLE pipe_handle; 1100 uv_stdio_container_t stdio[2]; 1101 1102 init_process_options("spawn_helper2", exit_cb); 1103 1104 uv_pipe_init(uv_default_loop(), &out, 0); 1105 options.stdio = stdio; 1106 options.stdio[0].flags = UV_IGNORE; 1107 options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; 1108 options.stdio[1].data.stream = (uv_stream_t*) &out; 1109 options.stdio_count = 2; 1110 1111 /* Create a pipe that'll cause a collision. */ 1112 snprintf(name, 1113 sizeof(name), 1114 "\\\\.\\pipe\\uv\\%p-%lu", 1115 &out, 1116 GetCurrentProcessId()); 1117 pipe_handle = CreateNamedPipeA(name, 1118 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 1119 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1120 10, 1121 65536, 1122 65536, 1123 0, 1124 NULL); 1125 ASSERT_PTR_NE(pipe_handle, INVALID_HANDLE_VALUE); 1126 1127 r = uv_spawn(uv_default_loop(), &process, &options); 1128 ASSERT_OK(r); 1129 1130 r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); 1131 ASSERT_OK(r); 1132 1133 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1134 ASSERT_OK(r); 1135 1136 ASSERT_EQ(1, exit_cb_called); 1137 ASSERT_EQ(2, close_cb_called); /* Once for process once for the pipe. */ 1138 printf("output is: %s", output); 1139 ASSERT_OK(strcmp("hello world\n", output)); 1140 1141 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1142 return 0; 1143 } 1144 1145 1146 #if !defined(USING_UV_SHARED) 1147 int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr); 1148 WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target); 1149 1150 TEST_IMPL(argument_escaping) { 1151 const WCHAR* test_str[] = { 1152 L"", 1153 L"HelloWorld", 1154 L"Hello World", 1155 L"Hello\"World", 1156 L"Hello World\\", 1157 L"Hello\\\"World", 1158 L"Hello\\World", 1159 L"Hello\\\\World", 1160 L"Hello World\\", 1161 L"c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"" 1162 }; 1163 const int count = sizeof(test_str) / sizeof(*test_str); 1164 WCHAR** test_output; 1165 WCHAR* command_line; 1166 WCHAR** cracked; 1167 size_t total_size = 0; 1168 int i; 1169 int num_args; 1170 int result; 1171 1172 char* verbatim[] = { 1173 "cmd.exe", 1174 "/c", 1175 "c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"", 1176 NULL 1177 }; 1178 WCHAR* verbatim_output; 1179 WCHAR* non_verbatim_output; 1180 1181 test_output = calloc(count, sizeof(WCHAR*)); 1182 ASSERT_NOT_NULL(test_output); 1183 for (i = 0; i < count; ++i) { 1184 test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR)); 1185 quote_cmd_arg(test_str[i], test_output[i]); 1186 wprintf(L"input : %s\n", test_str[i]); 1187 wprintf(L"output: %s\n", test_output[i]); 1188 total_size += wcslen(test_output[i]) + 1; 1189 } 1190 command_line = calloc(total_size + 1, sizeof(WCHAR)); 1191 ASSERT_NOT_NULL(command_line); 1192 for (i = 0; i < count; ++i) { 1193 wcscat(command_line, test_output[i]); 1194 wcscat(command_line, L" "); 1195 } 1196 command_line[total_size - 1] = L'\0'; 1197 1198 wprintf(L"command_line: %s\n", command_line); 1199 1200 cracked = CommandLineToArgvW(command_line, &num_args); 1201 for (i = 0; i < num_args; ++i) { 1202 wprintf(L"%d: %s\t%s\n", i, test_str[i], cracked[i]); 1203 ASSERT_OK(wcscmp(test_str[i], cracked[i])); 1204 } 1205 1206 LocalFree(cracked); 1207 for (i = 0; i < count; ++i) { 1208 free(test_output[i]); 1209 } 1210 free(test_output); 1211 1212 result = make_program_args(verbatim, 1, &verbatim_output); 1213 ASSERT_OK(result); 1214 result = make_program_args(verbatim, 0, &non_verbatim_output); 1215 ASSERT_OK(result); 1216 1217 wprintf(L" verbatim_output: %s\n", verbatim_output); 1218 wprintf(L"non_verbatim_output: %s\n", non_verbatim_output); 1219 1220 ASSERT_OK(wcscmp(verbatim_output, 1221 L"cmd.exe /c c:\\path\\to\\node.exe --eval " 1222 L"\"require('c:\\\\path\\\\to\\\\test.js')\"")); 1223 ASSERT_OK(wcscmp(non_verbatim_output, 1224 L"cmd.exe /c \"c:\\path\\to\\node.exe --eval " 1225 L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"")); 1226 1227 free(verbatim_output); 1228 free(non_verbatim_output); 1229 1230 return 0; 1231 } 1232 1233 int make_program_env(char** env_block, WCHAR** dst_ptr); 1234 1235 TEST_IMPL(environment_creation) { 1236 size_t i; 1237 char* environment[] = { 1238 "FOO=BAR", 1239 "SYSTEM=ROOT", /* substring of a supplied var name */ 1240 "SYSTEMROOTED=OMG", /* supplied var name is a substring */ 1241 "TEMP=C:\\Temp", 1242 "INVALID", 1243 "BAZ=QUX", 1244 "B_Z=QUX", 1245 "B\xe2\x82\xacZ=QUX", 1246 "B\xf0\x90\x80\x82Z=QUX", 1247 "B\xef\xbd\xa1Z=QUX", 1248 "B\xf0\xa3\x91\x96Z=QUX", 1249 "BAZ", /* repeat, invalid variable */ 1250 NULL 1251 }; 1252 WCHAR* wenvironment[] = { 1253 L"BAZ=QUX", 1254 L"B_Z=QUX", 1255 L"B\x20acZ=QUX", 1256 L"B\xd800\xdc02Z=QUX", 1257 L"B\xd84d\xdc56Z=QUX", 1258 L"B\xff61Z=QUX", 1259 L"FOO=BAR", 1260 L"SYSTEM=ROOT", /* substring of a supplied var name */ 1261 L"SYSTEMROOTED=OMG", /* supplied var name is a substring */ 1262 L"TEMP=C:\\Temp", 1263 }; 1264 WCHAR* from_env[] = { 1265 /* list should be kept in sync with list 1266 * in process.c, minus variables in wenvironment */ 1267 L"HOMEDRIVE", 1268 L"HOMEPATH", 1269 L"LOGONSERVER", 1270 L"PATH", 1271 L"USERDOMAIN", 1272 L"USERNAME", 1273 L"USERPROFILE", 1274 L"SYSTEMDRIVE", 1275 L"SYSTEMROOT", 1276 L"WINDIR", 1277 /* test for behavior in the absence of a 1278 * required-environment variable: */ 1279 L"ZTHIS_ENV_VARIABLE_DOES_NOT_EXIST", 1280 }; 1281 int found_in_loc_env[ARRAY_SIZE(wenvironment)] = {0}; 1282 int found_in_usr_env[ARRAY_SIZE(from_env)] = {0}; 1283 WCHAR *expected[ARRAY_SIZE(from_env)]; 1284 int result; 1285 WCHAR* str; 1286 WCHAR* prev; 1287 WCHAR* env; 1288 1289 for (i = 0; i < ARRAY_SIZE(from_env); i++) { 1290 /* copy expected additions to environment locally */ 1291 size_t len = GetEnvironmentVariableW(from_env[i], NULL, 0); 1292 if (len == 0) { 1293 found_in_usr_env[i] = 1; 1294 str = malloc(1 * sizeof(WCHAR)); 1295 *str = 0; 1296 expected[i] = str; 1297 } else { 1298 size_t name_len = wcslen(from_env[i]); 1299 str = malloc((name_len+1+len) * sizeof(WCHAR)); 1300 wmemcpy(str, from_env[i], name_len); 1301 expected[i] = str; 1302 str += name_len; 1303 *str++ = L'='; 1304 GetEnvironmentVariableW(from_env[i], str, len); 1305 } 1306 } 1307 1308 result = make_program_env(environment, &env); 1309 ASSERT_OK(result); 1310 1311 for (str = env, prev = NULL; *str; prev = str, str += wcslen(str) + 1) { 1312 int found = 0; 1313 #if 0 1314 _cputws(str); 1315 putchar('\n'); 1316 #endif 1317 for (i = 0; i < ARRAY_SIZE(wenvironment) && !found; i++) { 1318 if (!wcscmp(str, wenvironment[i])) { 1319 ASSERT(!found_in_loc_env[i]); 1320 found_in_loc_env[i] = 1; 1321 found = 1; 1322 } 1323 } 1324 for (i = 0; i < ARRAY_SIZE(expected) && !found; i++) { 1325 if (!wcscmp(str, expected[i])) { 1326 ASSERT(!found_in_usr_env[i]); 1327 found_in_usr_env[i] = 1; 1328 found = 1; 1329 } 1330 } 1331 if (prev) { /* verify sort order */ 1332 ASSERT_EQ(1, CompareStringOrdinal(prev, -1, str, -1, TRUE)); 1333 } 1334 ASSERT(found); /* verify that we expected this variable */ 1335 } 1336 1337 /* verify that we found all expected variables */ 1338 for (i = 0; i < ARRAY_SIZE(wenvironment); i++) { 1339 ASSERT(found_in_loc_env[i]); 1340 } 1341 for (i = 0; i < ARRAY_SIZE(expected); i++) { 1342 ASSERT(found_in_usr_env[i]); 1343 } 1344 1345 return 0; 1346 } 1347 #endif 1348 1349 /* Regression test for issue #909 */ 1350 TEST_IMPL(spawn_with_an_odd_path) { 1351 int r; 1352 1353 char newpath[2048]; 1354 char *path = getenv("PATH"); 1355 ASSERT_NOT_NULL(path); 1356 snprintf(newpath, 2048, ";.;%s", path); 1357 SetEnvironmentVariable("PATH", newpath); 1358 1359 init_process_options("", exit_cb); 1360 options.file = options.args[0] = "program-that-had-better-not-exist"; 1361 r = uv_spawn(uv_default_loop(), &process, &options); 1362 ASSERT(r == UV_ENOENT || r == UV_EACCES); 1363 ASSERT_OK(uv_is_active((uv_handle_t*) &process)); 1364 uv_close((uv_handle_t*) &process, NULL); 1365 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1366 1367 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1368 return 0; 1369 } 1370 1371 1372 TEST_IMPL(spawn_no_path) { 1373 char* env[1]; 1374 WCHAR* old_path = NULL; 1375 DWORD old_path_len; 1376 1377 if ((old_path_len = GetEnvironmentVariableW(L"PATH", NULL, 0)) > 0) { 1378 old_path = malloc(old_path_len * sizeof(WCHAR)); 1379 GetEnvironmentVariableW(L"PATH", old_path, old_path_len); 1380 SetEnvironmentVariableW(L"PATH", NULL); 1381 } 1382 1383 init_process_options("spawn_helper1", exit_cb); 1384 options.env = env; 1385 env[0] = NULL; 1386 1387 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1388 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1389 1390 ASSERT_EQ(1, exit_cb_called); 1391 ASSERT_EQ(1, close_cb_called); 1392 1393 SetEnvironmentVariableW(L"PATH", old_path); 1394 1395 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1396 return 0; 1397 } 1398 1399 1400 TEST_IMPL(spawn_no_ext) { 1401 char new_exepath[1024]; 1402 1403 init_process_options("spawn_helper1", exit_cb); 1404 options.flags |= UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME; 1405 snprintf(new_exepath, sizeof(new_exepath), "%.*s_no_ext", 1406 (int) (exepath_size - sizeof(".exe") + 1), 1407 exepath); 1408 options.file = options.args[0] = new_exepath; 1409 1410 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1411 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1412 1413 ASSERT_EQ(1, exit_cb_called); 1414 ASSERT_EQ(1, close_cb_called); 1415 1416 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1417 return 0; 1418 } 1419 1420 1421 TEST_IMPL(spawn_path_no_ext) { 1422 int r; 1423 int len; 1424 int file_len; 1425 char file[64]; 1426 char path[1024]; 1427 char* env[2]; 1428 1429 /* Set up the process, but make sure that the file to run is relative and 1430 * requires a lookup into PATH. */ 1431 init_process_options("spawn_helper1", exit_cb); 1432 options.flags |= UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME; 1433 1434 /* Set up the PATH env variable */ 1435 for (len = strlen(exepath), file_len = 0; 1436 exepath[len - 1] != '/' && exepath[len - 1] != '\\'; 1437 len--, file_len++); 1438 snprintf(file, sizeof(file), "%.*s_no_ext", 1439 (int) (file_len - sizeof(".exe") + 1), 1440 exepath + len); 1441 exepath[len] = 0; 1442 snprintf(path, sizeof(path), "PATH=%s", exepath); 1443 1444 env[0] = path; 1445 env[1] = NULL; 1446 1447 options.file = options.args[0] = file; 1448 options.env = env; 1449 1450 r = uv_spawn(uv_default_loop(), &process, &options); 1451 ASSERT(r == UV_ENOENT || r == UV_EACCES); 1452 ASSERT_OK(uv_is_active((uv_handle_t*) &process)); 1453 uv_close((uv_handle_t*) &process, NULL); 1454 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1455 1456 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1457 return 0; 1458 } 1459 #endif 1460 1461 #ifndef _WIN32 1462 TEST_IMPL(spawn_setuid_setgid) { 1463 int r; 1464 struct passwd* pw; 1465 char uidstr[10]; 1466 char gidstr[10]; 1467 1468 /* if not root, then this will fail. */ 1469 uv_uid_t uid = getuid(); 1470 if (uid != 0) { 1471 RETURN_SKIP("It should be run as root user"); 1472 } 1473 1474 init_process_options("spawn_helper_setuid_setgid", exit_cb); 1475 1476 /* become the "nobody" user. */ 1477 pw = getpwnam("nobody"); 1478 ASSERT_NOT_NULL(pw); 1479 options.uid = pw->pw_uid; 1480 options.gid = pw->pw_gid; 1481 snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid); 1482 snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid); 1483 options.args[2] = uidstr; 1484 options.args[3] = gidstr; 1485 options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; 1486 1487 r = uv_spawn(uv_default_loop(), &process, &options); 1488 if (r == UV_EACCES) 1489 RETURN_SKIP("user 'nobody' cannot access the test runner"); 1490 1491 ASSERT_OK(r); 1492 1493 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1494 ASSERT_OK(r); 1495 1496 ASSERT_EQ(1, exit_cb_called); 1497 ASSERT_EQ(1, close_cb_called); 1498 1499 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1500 return 0; 1501 } 1502 #endif 1503 1504 1505 #ifndef _WIN32 1506 TEST_IMPL(spawn_setuid_fails) { 1507 int r; 1508 1509 /* if root, become nobody. */ 1510 /* On IBMi PASE, there is no nobody user. */ 1511 #ifndef __PASE__ 1512 uv_uid_t uid = getuid(); 1513 if (uid == 0) { 1514 struct passwd* pw; 1515 pw = getpwnam("nobody"); 1516 ASSERT_NOT_NULL(pw); 1517 ASSERT_OK(setgid(pw->pw_gid)); 1518 ASSERT_OK(setuid(pw->pw_uid)); 1519 } 1520 #endif /* !__PASE__ */ 1521 1522 init_process_options("spawn_helper1", fail_cb); 1523 1524 options.flags |= UV_PROCESS_SETUID; 1525 /* On IBMi PASE, there is no root user. User may grant 1526 * root-like privileges, including setting uid to 0. 1527 */ 1528 #if defined(__PASE__) 1529 options.uid = -1; 1530 #else 1531 options.uid = 0; 1532 #endif 1533 1534 /* These flags should be ignored on Unices. */ 1535 options.flags |= UV_PROCESS_WINDOWS_HIDE; 1536 options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE; 1537 options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI; 1538 options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; 1539 1540 r = uv_spawn(uv_default_loop(), &process, &options); 1541 #if defined(__CYGWIN__) 1542 ASSERT_EQ(r, UV_EINVAL); 1543 #else 1544 ASSERT_EQ(r, UV_EPERM); 1545 #endif 1546 1547 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1548 ASSERT_OK(r); 1549 1550 ASSERT_OK(close_cb_called); 1551 1552 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1553 return 0; 1554 } 1555 1556 1557 TEST_IMPL(spawn_setgid_fails) { 1558 int r; 1559 1560 /* if root, become nobody. */ 1561 /* On IBMi PASE, there is no nobody user. */ 1562 #ifndef __PASE__ 1563 uv_uid_t uid = getuid(); 1564 if (uid == 0) { 1565 struct passwd* pw; 1566 pw = getpwnam("nobody"); 1567 ASSERT_NOT_NULL(pw); 1568 ASSERT_OK(setgid(pw->pw_gid)); 1569 ASSERT_OK(setuid(pw->pw_uid)); 1570 } 1571 #endif /* !__PASE__ */ 1572 1573 init_process_options("spawn_helper1", fail_cb); 1574 1575 options.flags |= UV_PROCESS_SETGID; 1576 /* On IBMi PASE, there is no root user. User may grant 1577 * root-like privileges, including setting gid to 0. 1578 */ 1579 #if defined(__MVS__) || defined(__PASE__) 1580 options.gid = -1; 1581 #else 1582 options.gid = 0; 1583 #endif 1584 1585 r = uv_spawn(uv_default_loop(), &process, &options); 1586 #if defined(__CYGWIN__) || defined(__MVS__) 1587 ASSERT_EQ(r, UV_EINVAL); 1588 #else 1589 ASSERT_EQ(r, UV_EPERM); 1590 #endif 1591 1592 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1593 ASSERT_OK(r); 1594 1595 ASSERT_OK(close_cb_called); 1596 1597 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1598 return 0; 1599 } 1600 #endif 1601 1602 1603 #ifdef _WIN32 1604 1605 static void exit_cb_unexpected(uv_process_t* process, 1606 int64_t exit_status, 1607 int term_signal) { 1608 ASSERT(0 && "should not have been called"); 1609 } 1610 1611 1612 TEST_IMPL(spawn_setuid_fails) { 1613 int r; 1614 1615 init_process_options("spawn_helper1", exit_cb_unexpected); 1616 1617 options.flags |= UV_PROCESS_SETUID; 1618 options.uid = (uv_uid_t) -42424242; 1619 1620 r = uv_spawn(uv_default_loop(), &process, &options); 1621 ASSERT_EQ(r, UV_ENOTSUP); 1622 1623 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1624 ASSERT_OK(r); 1625 1626 ASSERT_OK(close_cb_called); 1627 1628 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1629 return 0; 1630 } 1631 1632 1633 TEST_IMPL(spawn_setgid_fails) { 1634 int r; 1635 1636 init_process_options("spawn_helper1", exit_cb_unexpected); 1637 1638 options.flags |= UV_PROCESS_SETGID; 1639 options.gid = (uv_gid_t) -42424242; 1640 1641 r = uv_spawn(uv_default_loop(), &process, &options); 1642 ASSERT_EQ(r, UV_ENOTSUP); 1643 1644 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1645 ASSERT_OK(r); 1646 1647 ASSERT_OK(close_cb_called); 1648 1649 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1650 return 0; 1651 } 1652 #endif 1653 1654 1655 TEST_IMPL(spawn_auto_unref) { 1656 init_process_options("spawn_helper1", NULL); 1657 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1658 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1659 ASSERT_OK(uv_is_closing((uv_handle_t*) &process)); 1660 uv_close((uv_handle_t*) &process, NULL); 1661 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1662 ASSERT_EQ(1, uv_is_closing((uv_handle_t*) &process)); 1663 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1664 return 0; 1665 } 1666 1667 1668 TEST_IMPL(spawn_fs_open) { 1669 int r; 1670 uv_os_fd_t fd; 1671 uv_os_fd_t dup_fd; 1672 uv_fs_t fs_req; 1673 uv_pipe_t in; 1674 uv_write_t write_req; 1675 uv_write_t write_req2; 1676 uv_buf_t buf; 1677 uv_stdio_container_t stdio[1]; 1678 #ifdef _WIN32 1679 const char dev_null[] = "NUL"; 1680 HMODULE kernelbase_module; 1681 sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */ 1682 #else 1683 const char dev_null[] = "/dev/null"; 1684 #endif 1685 1686 r = uv_fs_open(NULL, &fs_req, dev_null, UV_FS_O_RDWR, 0, NULL); 1687 ASSERT_NE(r, -1); 1688 fd = uv_get_osfhandle((uv_file) fs_req.result); 1689 uv_fs_req_cleanup(&fs_req); 1690 1691 init_process_options("spawn_helper8", exit_cb); 1692 1693 ASSERT_OK(uv_pipe_init(uv_default_loop(), &in, 0)); 1694 1695 options.stdio = stdio; 1696 options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 1697 options.stdio[0].data.stream = (uv_stream_t*) ∈ 1698 options.stdio_count = 1; 1699 1700 /* make an inheritable copy */ 1701 #ifdef _WIN32 1702 ASSERT_NE(0, DuplicateHandle(GetCurrentProcess(), fd, GetCurrentProcess(), &dup_fd, 1703 0, /* inherit */ TRUE, DUPLICATE_SAME_ACCESS)); 1704 kernelbase_module = GetModuleHandleA("kernelbase.dll"); 1705 pCompareObjectHandles = (sCompareObjectHandles) 1706 GetProcAddress(kernelbase_module, "CompareObjectHandles"); 1707 ASSERT_NE(pCompareObjectHandles == NULL || 1708 pCompareObjectHandles(fd, dup_fd), 1709 0); 1710 #else 1711 dup_fd = dup(fd); 1712 #endif 1713 1714 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1715 1716 buf = uv_buf_init((char*) &fd, sizeof(fd)); 1717 ASSERT_OK(uv_write(&write_req, 1718 (uv_stream_t*) &in, 1719 &buf, 1720 1, 1721 write_null_cb)); 1722 1723 buf = uv_buf_init((char*) &dup_fd, sizeof(fd)); 1724 ASSERT_OK(uv_write(&write_req2, (uv_stream_t*) &in, &buf, 1, write_cb)); 1725 1726 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 1727 ASSERT_OK(uv_fs_close(NULL, &fs_req, r, NULL)); 1728 1729 ASSERT_EQ(1, exit_cb_called); 1730 ASSERT_EQ(2, close_cb_called); /* One for `in`, one for process */ 1731 1732 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1733 return 0; 1734 } 1735 1736 1737 TEST_IMPL(closed_fd_events) { 1738 uv_stdio_container_t stdio[3]; 1739 uv_pipe_t pipe_handle; 1740 uv_fs_t req; 1741 uv_buf_t bufs[1]; 1742 uv_file fd[2]; 1743 bufs[0] = uv_buf_init("", 1); 1744 1745 /* create a pipe and share it with a child process */ 1746 ASSERT_OK(uv_pipe(fd, 0, 0)); 1747 ASSERT_GT(fd[0], 2); 1748 ASSERT_GT(fd[1], 2); 1749 1750 /* spawn_helper4 blocks indefinitely. */ 1751 init_process_options("spawn_helper4", exit_cb); 1752 options.stdio_count = 3; 1753 options.stdio = stdio; 1754 options.stdio[0].flags = UV_INHERIT_FD; 1755 options.stdio[0].data.fd = fd[0]; 1756 options.stdio[1].flags = UV_IGNORE; 1757 options.stdio[2].flags = UV_IGNORE; 1758 1759 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 1760 uv_unref((uv_handle_t*) &process); 1761 1762 /* read from the pipe with uv */ 1763 ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); 1764 ASSERT_OK(uv_pipe_open(&pipe_handle, fd[0])); 1765 /* uv_pipe_open() takes ownership of the file descriptor. */ 1766 fd[0] = -1; 1767 1768 ASSERT_OK(uv_read_start((uv_stream_t*) &pipe_handle, 1769 on_alloc, 1770 on_read_once)); 1771 1772 ASSERT_EQ(1, uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL)); 1773 ASSERT_EQ(1, req.result); 1774 uv_fs_req_cleanup(&req); 1775 1776 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE)); 1777 1778 /* should have received just one byte */ 1779 ASSERT_EQ(1, output_used); 1780 1781 /* close the pipe and see if we still get events */ 1782 uv_close((uv_handle_t*) &pipe_handle, close_cb); 1783 1784 ASSERT_EQ(1, uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL)); 1785 ASSERT_EQ(1, req.result); 1786 uv_fs_req_cleanup(&req); 1787 1788 ASSERT_OK(uv_timer_init(uv_default_loop(), &timer)); 1789 ASSERT_OK(uv_timer_start(&timer, timer_counter_cb, 10, 0)); 1790 1791 /* see if any spurious events interrupt the timer */ 1792 if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE)) 1793 /* have to run again to really trigger the timer */ 1794 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE)); 1795 1796 ASSERT_EQ(1, timer_counter); 1797 1798 /* cleanup */ 1799 ASSERT_OK(uv_process_kill(&process, SIGTERM)); 1800 #ifdef _WIN32 1801 ASSERT_OK(_close(fd[1])); 1802 #else 1803 ASSERT_OK(close(fd[1])); 1804 #endif 1805 1806 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1807 return 0; 1808 } 1809 1810 1811 TEST_IMPL(spawn_reads_child_path) { 1812 int r; 1813 int len; 1814 char file[64]; 1815 char path[1024]; 1816 char* env[3]; 1817 1818 /* Need to carry over the dynamic linker path when the test runner is 1819 * linked against libuv.so, see https://github.com/libuv/libuv/issues/85. 1820 */ 1821 #if defined(__APPLE__) 1822 static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; 1823 #elif defined(__MVS__) || defined(__PASE__) 1824 static const char dyld_path_var[] = "LIBPATH"; 1825 #else 1826 static const char dyld_path_var[] = "LD_LIBRARY_PATH"; 1827 #endif 1828 1829 /* Set up the process, but make sure that the file to run is relative and 1830 * requires a lookup into PATH. */ 1831 init_process_options("spawn_helper1", exit_cb); 1832 1833 /* Set up the PATH env variable */ 1834 for (len = strlen(exepath); 1835 exepath[len - 1] != '/' && exepath[len - 1] != '\\'; 1836 len--); 1837 strcpy(file, exepath + len); 1838 exepath[len] = 0; 1839 strcpy(path, "PATH="); 1840 strcpy(path + 5, exepath); 1841 #if defined(__CYGWIN__) || defined(__MSYS__) 1842 /* Carry over the dynamic linker path in case the test runner 1843 is linked against cyguv-1.dll or msys-uv-1.dll, see above. */ 1844 { 1845 char* syspath = getenv("PATH"); 1846 if (syspath != NULL) { 1847 strcat(path, ":"); 1848 strcat(path, syspath); 1849 } 1850 } 1851 #endif 1852 1853 env[0] = path; 1854 env[1] = getenv(dyld_path_var); 1855 env[2] = NULL; 1856 1857 if (env[1] != NULL) { 1858 static char buf[1024 + sizeof(dyld_path_var)]; 1859 snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]); 1860 env[1] = buf; 1861 } 1862 1863 options.file = file; 1864 options.args[0] = file; 1865 options.env = env; 1866 1867 r = uv_spawn(uv_default_loop(), &process, &options); 1868 ASSERT_OK(r); 1869 1870 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 1871 ASSERT_OK(r); 1872 1873 ASSERT_EQ(1, exit_cb_called); 1874 ASSERT_EQ(1, close_cb_called); 1875 1876 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1877 return 0; 1878 } 1879 1880 TEST_IMPL(spawn_inherit_streams) { 1881 uv_process_t child_req; 1882 uv_stdio_container_t child_stdio[2]; 1883 int fds_stdin[2]; 1884 int fds_stdout[2]; 1885 uv_pipe_t pipe_stdin_child; 1886 uv_pipe_t pipe_stdout_child; 1887 uv_pipe_t pipe_stdin_parent; 1888 uv_pipe_t pipe_stdout_parent; 1889 unsigned char ubuf[OUTPUT_SIZE - 1]; 1890 uv_buf_t buf; 1891 unsigned int i; 1892 int r; 1893 int bidir; 1894 uv_write_t write_req; 1895 uv_loop_t* loop; 1896 1897 init_process_options("spawn_helper9", exit_cb); 1898 1899 loop = uv_default_loop(); 1900 ASSERT_OK(uv_pipe_init(loop, &pipe_stdin_child, 0)); 1901 ASSERT_OK(uv_pipe_init(loop, &pipe_stdout_child, 0)); 1902 ASSERT_OK(uv_pipe_init(loop, &pipe_stdin_parent, 0)); 1903 ASSERT_OK(uv_pipe_init(loop, &pipe_stdout_parent, 0)); 1904 1905 ASSERT_OK(uv_pipe(fds_stdin, 0, 0)); 1906 ASSERT_OK(uv_pipe(fds_stdout, 0, 0)); 1907 1908 ASSERT_OK(uv_pipe_open(&pipe_stdin_child, fds_stdin[0])); 1909 ASSERT_OK(uv_pipe_open(&pipe_stdout_child, fds_stdout[1])); 1910 ASSERT_OK(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1])); 1911 ASSERT_OK(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0])); 1912 ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_child)); 1913 ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_child)); 1914 ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdin_parent)); 1915 ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_parent)); 1916 /* Some systems (SVR4) open a bidirectional pipe, most don't. */ 1917 bidir = uv_is_writable((uv_stream_t*) &pipe_stdin_child); 1918 ASSERT_EQ(uv_is_readable((uv_stream_t*) &pipe_stdout_child), bidir); 1919 ASSERT_EQ(uv_is_readable((uv_stream_t*) &pipe_stdin_parent), bidir); 1920 ASSERT_EQ(uv_is_writable((uv_stream_t*) &pipe_stdout_parent), bidir); 1921 1922 child_stdio[0].flags = UV_INHERIT_STREAM; 1923 child_stdio[0].data.stream = (uv_stream_t *) &pipe_stdin_child; 1924 1925 child_stdio[1].flags = UV_INHERIT_STREAM; 1926 child_stdio[1].data.stream = (uv_stream_t *) &pipe_stdout_child; 1927 1928 options.stdio = child_stdio; 1929 options.stdio_count = 2; 1930 1931 ASSERT_OK(uv_spawn(loop, &child_req, &options)); 1932 1933 uv_close((uv_handle_t*) &pipe_stdin_child, NULL); 1934 uv_close((uv_handle_t*) &pipe_stdout_child, NULL); 1935 1936 buf = uv_buf_init((char*) ubuf, sizeof ubuf); 1937 for (i = 0; i < sizeof ubuf; ++i) 1938 ubuf[i] = i & 255u; 1939 memset(output, 0, sizeof ubuf); 1940 1941 r = uv_write(&write_req, 1942 (uv_stream_t*) &pipe_stdin_parent, 1943 &buf, 1944 1, 1945 write_cb); 1946 ASSERT_OK(r); 1947 1948 r = uv_read_start((uv_stream_t*) &pipe_stdout_parent, on_alloc, on_read); 1949 ASSERT_OK(r); 1950 1951 r = uv_run(loop, UV_RUN_DEFAULT); 1952 ASSERT_OK(r); 1953 1954 ASSERT_EQ(1, exit_cb_called); 1955 ASSERT_EQ(3, close_cb_called); 1956 1957 r = memcmp(ubuf, output, sizeof ubuf); 1958 ASSERT_OK(r); 1959 1960 MAKE_VALGRIND_HAPPY(loop); 1961 return 0; 1962 } 1963 1964 TEST_IMPL(spawn_quoted_path) { 1965 #ifndef _WIN32 1966 RETURN_SKIP("Test for Windows"); 1967 #else 1968 char* quoted_path_env[2]; 1969 args[0] = "not_existing"; 1970 args[1] = NULL; 1971 options.file = args[0]; 1972 options.args = args; 1973 options.exit_cb = exit_cb; 1974 options.flags = 0; 1975 /* We test if search_path works correctly with semicolons in quoted path. We 1976 * will use an invalid drive, so we are sure no executable is spawned. */ 1977 quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other"; 1978 quoted_path_env[1] = NULL; 1979 options.env = quoted_path_env; 1980 1981 /* We test if libuv will not segfault. */ 1982 uv_spawn(uv_default_loop(), &process, &options); 1983 1984 MAKE_VALGRIND_HAPPY(uv_default_loop()); 1985 return 0; 1986 #endif 1987 } 1988 1989 TEST_IMPL(spawn_exercise_sigchld_issue) { 1990 int r; 1991 int i; 1992 uv_process_options_t dummy_options = {0}; 1993 uv_process_t dummy_processes[100]; 1994 char* args[2]; 1995 1996 init_process_options("spawn_helper1", exit_cb); 1997 1998 r = uv_spawn(uv_default_loop(), &process, &options); 1999 ASSERT_OK(r); 2000 2001 // This test exercises a bug in the darwin kernel that causes SIGCHLD not to 2002 // be delivered sometimes. Calling posix_spawn many times increases the 2003 // likelihood of encountering this issue, so spin a few times to make this 2004 // test more reliable. 2005 dummy_options.file = args[0] = "program-that-had-better-not-exist"; 2006 args[1] = NULL; 2007 dummy_options.args = args; 2008 dummy_options.exit_cb = fail_cb; 2009 dummy_options.flags = 0; 2010 for (i = 0; i < 100; i++) { 2011 r = uv_spawn(uv_default_loop(), &dummy_processes[i], &dummy_options); 2012 if (r != UV_ENOENT) 2013 ASSERT_EQ(r, UV_EACCES); 2014 uv_close((uv_handle_t*) &dummy_processes[i], close_cb); 2015 } 2016 2017 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); 2018 ASSERT_OK(r); 2019 2020 ASSERT_EQ(1, exit_cb_called); 2021 ASSERT_EQ(101, close_cb_called); 2022 2023 MAKE_VALGRIND_HAPPY(uv_default_loop()); 2024 return 0; 2025 } 2026 2027 /* Helper for child process of spawn_inherit_streams */ 2028 #ifndef _WIN32 2029 void spawn_stdin_stdout(void) { 2030 char buf[1024]; 2031 char* pbuf; 2032 for (;;) { 2033 ssize_t r, w, c; 2034 do { 2035 r = read(0, buf, sizeof buf); 2036 } while (r == -1 && errno == EINTR); 2037 if (r == 0) { 2038 return; 2039 } 2040 ASSERT_GT(r, 0); 2041 c = r; 2042 pbuf = buf; 2043 while (c) { 2044 do { 2045 w = write(1, pbuf, (size_t)c); 2046 } while (w == -1 && errno == EINTR); 2047 ASSERT_GE(w, 0); 2048 pbuf = pbuf + w; 2049 c = c - w; 2050 } 2051 } 2052 } 2053 #else 2054 void spawn_stdin_stdout(void) { 2055 char buf[1024]; 2056 char* pbuf; 2057 HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE); 2058 HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); 2059 ASSERT_PTR_NE(h_stdin, INVALID_HANDLE_VALUE); 2060 ASSERT_PTR_NE(h_stdout, INVALID_HANDLE_VALUE); 2061 for (;;) { 2062 DWORD n_read; 2063 DWORD n_written; 2064 DWORD to_write; 2065 if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) { 2066 ASSERT_EQ(GetLastError(), ERROR_BROKEN_PIPE); 2067 return; 2068 } 2069 to_write = n_read; 2070 pbuf = buf; 2071 while (to_write) { 2072 ASSERT(WriteFile(h_stdout, pbuf, to_write, &n_written, NULL)); 2073 to_write -= n_written; 2074 pbuf += n_written; 2075 } 2076 } 2077 } 2078 #endif /* !_WIN32 */ 2079 2080 TEST_IMPL(spawn_relative_path) { 2081 char* sep; 2082 2083 init_process_options("spawn_helper1", exit_cb); 2084 2085 exepath_size = sizeof(exepath) - 2; 2086 ASSERT_OK(uv_exepath(exepath, &exepath_size)); 2087 exepath[exepath_size] = '\0'; 2088 2089 /* Poor man's basename(3). */ 2090 sep = strrchr(exepath, '/'); 2091 if (sep == NULL) 2092 sep = strrchr(exepath, '\\'); 2093 ASSERT_NOT_NULL(sep); 2094 2095 /* Split into dirname and basename and make basename relative. */ 2096 memmove(sep + 2, sep, 1 + strlen(sep)); 2097 sep[0] = '\0'; 2098 sep[1] = '.'; 2099 sep[2] = '/'; 2100 2101 options.cwd = exepath; 2102 options.file = options.args[0] = sep + 1; 2103 2104 ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options)); 2105 ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 2106 2107 ASSERT_EQ(1, exit_cb_called); 2108 ASSERT_EQ(1, close_cb_called); 2109 2110 MAKE_VALGRIND_HAPPY(uv_default_loop()); 2111 return 0; 2112 } 2113