libuv-svace-build

Форк
0
/
test-spawn.c 
2113 строк · 53.4 Кб
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*) &in;
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*) &in;
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*) &in;
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*) &in;
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*) &in;
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
#if !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)
1333
      ASSERT_EQ(1, CompareStringOrdinal(prev, -1, str, -1, TRUE));
1334
#endif
1335
    }
1336
    ASSERT(found); /* verify that we expected this variable */
1337
  }
1338

1339
  /* verify that we found all expected variables */
1340
  for (i = 0; i < ARRAY_SIZE(wenvironment); i++) {
1341
    ASSERT(found_in_loc_env[i]);
1342
  }
1343
  for (i = 0; i < ARRAY_SIZE(expected); i++) {
1344
    ASSERT(found_in_usr_env[i]);
1345
  }
1346

1347
  return 0;
1348
}
1349
#endif
1350

1351
/* Regression test for issue #909 */
1352
TEST_IMPL(spawn_with_an_odd_path) {
1353
  int r;
1354

1355
  char newpath[2048];
1356
  char *path = getenv("PATH");
1357
  ASSERT_NOT_NULL(path);
1358
  snprintf(newpath, 2048, ";.;%s", path);
1359
  SetEnvironmentVariable("PATH", newpath);
1360

1361
  init_process_options("", exit_cb);
1362
  options.file = options.args[0] = "program-that-had-better-not-exist";
1363
  r = uv_spawn(uv_default_loop(), &process, &options);
1364
  ASSERT(r == UV_ENOENT || r == UV_EACCES);
1365
  ASSERT_OK(uv_is_active((uv_handle_t*) &process));
1366
  uv_close((uv_handle_t*) &process, NULL);
1367
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1368

1369
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1370
  return 0;
1371
}
1372

1373

1374
TEST_IMPL(spawn_no_path) {
1375
  char* env[1];
1376
  WCHAR* old_path = NULL;
1377
  DWORD old_path_len;
1378

1379
  if ((old_path_len = GetEnvironmentVariableW(L"PATH", NULL, 0)) > 0) {
1380
    old_path = malloc(old_path_len * sizeof(WCHAR));
1381
    GetEnvironmentVariableW(L"PATH", old_path, old_path_len);
1382
    SetEnvironmentVariableW(L"PATH", NULL);
1383
  }
1384

1385
  init_process_options("spawn_helper1", exit_cb);
1386
  options.env = env;
1387
  env[0] = NULL;
1388

1389
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
1390
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1391

1392
  ASSERT_EQ(1, exit_cb_called);
1393
  ASSERT_EQ(1, close_cb_called);
1394

1395
  SetEnvironmentVariableW(L"PATH", old_path);
1396

1397
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1398
  return 0;
1399
}
1400

1401

1402
TEST_IMPL(spawn_no_ext) {
1403
  char new_exepath[1024];
1404

1405
  init_process_options("spawn_helper1", exit_cb);
1406
  options.flags |= UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME;
1407
  snprintf(new_exepath, sizeof(new_exepath), "%.*s_no_ext",
1408
           (int) (exepath_size - sizeof(".exe") + 1),
1409
           exepath);
1410
  options.file = options.args[0] = new_exepath;
1411

1412
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
1413
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1414

1415
  ASSERT_EQ(1, exit_cb_called);
1416
  ASSERT_EQ(1, close_cb_called);
1417

1418
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1419
  return 0;
1420
}
1421

1422

1423
TEST_IMPL(spawn_path_no_ext) {
1424
  int r;
1425
  int len;
1426
  int file_len;
1427
  char file[64];
1428
  char path[1024];
1429
  char* env[2];
1430

1431
  /* Set up the process, but make sure that the file to run is relative and
1432
   * requires a lookup into PATH. */
1433
  init_process_options("spawn_helper1", exit_cb);
1434
  options.flags |= UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME;
1435

1436
  /* Set up the PATH env variable */
1437
  for (len = strlen(exepath), file_len = 0;
1438
       exepath[len - 1] != '/' && exepath[len - 1] != '\\';
1439
       len--, file_len++);
1440
  snprintf(file, sizeof(file), "%.*s_no_ext",
1441
           (int) (file_len - sizeof(".exe") + 1),
1442
           exepath + len);
1443
  exepath[len] = 0;
1444
  snprintf(path, sizeof(path), "PATH=%s", exepath);
1445

1446
  env[0] = path;
1447
  env[1] = NULL;
1448

1449
  options.file = options.args[0] = file;
1450
  options.env = env;
1451

1452
  r = uv_spawn(uv_default_loop(), &process, &options);
1453
  ASSERT(r == UV_ENOENT || r == UV_EACCES);
1454
  ASSERT_OK(uv_is_active((uv_handle_t*) &process));
1455
  uv_close((uv_handle_t*) &process, NULL);
1456
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1457

1458
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1459
  return 0;
1460
}
1461
#endif
1462

1463
#ifndef _WIN32
1464
TEST_IMPL(spawn_setuid_setgid) {
1465
  int r;
1466
  struct passwd* pw;
1467
  char uidstr[10];
1468
  char gidstr[10];
1469

1470
  /* if not root, then this will fail. */
1471
  uv_uid_t uid = getuid();
1472
  if (uid != 0) {
1473
    RETURN_SKIP("It should be run as root user");
1474
  }
1475

1476
  init_process_options("spawn_helper_setuid_setgid", exit_cb);
1477

1478
  /* become the "nobody" user. */
1479
  pw = getpwnam("nobody");
1480
  ASSERT_NOT_NULL(pw);
1481
  options.uid = pw->pw_uid;
1482
  options.gid = pw->pw_gid;
1483
  snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
1484
  snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid);
1485
  options.args[2] = uidstr;
1486
  options.args[3] = gidstr;
1487
  options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
1488

1489
  r = uv_spawn(uv_default_loop(), &process, &options);
1490
  if (r == UV_EACCES)
1491
    RETURN_SKIP("user 'nobody' cannot access the test runner");
1492

1493
  ASSERT_OK(r);
1494

1495
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1496
  ASSERT_OK(r);
1497

1498
  ASSERT_EQ(1, exit_cb_called);
1499
  ASSERT_EQ(1, close_cb_called);
1500

1501
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1502
  return 0;
1503
}
1504
#endif
1505

1506

1507
#ifndef _WIN32
1508
TEST_IMPL(spawn_setuid_fails) {
1509
  int r;
1510

1511
  /* if root, become nobody. */
1512
  /* On IBMi PASE, there is no nobody user. */
1513
#ifndef __PASE__
1514
  uv_uid_t uid = getuid();
1515
  if (uid == 0) {
1516
    struct passwd* pw;
1517
    pw = getpwnam("nobody");
1518
    ASSERT_NOT_NULL(pw);
1519
    ASSERT_OK(setgid(pw->pw_gid));
1520
    ASSERT_OK(setuid(pw->pw_uid));
1521
  }
1522
#endif  /* !__PASE__ */
1523

1524
  init_process_options("spawn_helper1", fail_cb);
1525

1526
  options.flags |= UV_PROCESS_SETUID;
1527
  /* On IBMi PASE, there is no root user. User may grant 
1528
   * root-like privileges, including setting uid to 0.
1529
   */
1530
#if defined(__PASE__)
1531
  options.uid = -1;
1532
#else
1533
  options.uid = 0;
1534
#endif
1535

1536
  /* These flags should be ignored on Unices. */
1537
  options.flags |= UV_PROCESS_WINDOWS_HIDE;
1538
  options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE;
1539
  options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI;
1540
  options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
1541

1542
  r = uv_spawn(uv_default_loop(), &process, &options);
1543
#if defined(__CYGWIN__)
1544
  ASSERT_EQ(r, UV_EINVAL);
1545
#else
1546
  ASSERT_EQ(r, UV_EPERM);
1547
#endif
1548

1549
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1550
  ASSERT_OK(r);
1551

1552
  ASSERT_OK(close_cb_called);
1553

1554
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1555
  return 0;
1556
}
1557

1558

1559
TEST_IMPL(spawn_setgid_fails) {
1560
  int r;
1561

1562
  /* if root, become nobody. */
1563
  /* On IBMi PASE, there is no nobody user. */
1564
#ifndef __PASE__
1565
  uv_uid_t uid = getuid();
1566
  if (uid == 0) {
1567
    struct passwd* pw;
1568
    pw = getpwnam("nobody");
1569
    ASSERT_NOT_NULL(pw);
1570
    ASSERT_OK(setgid(pw->pw_gid));
1571
    ASSERT_OK(setuid(pw->pw_uid));
1572
  }
1573
#endif  /* !__PASE__ */
1574

1575
  init_process_options("spawn_helper1", fail_cb);
1576

1577
  options.flags |= UV_PROCESS_SETGID;
1578
  /* On IBMi PASE, there is no root user. User may grant 
1579
   * root-like privileges, including setting gid to 0.
1580
   */
1581
#if defined(__MVS__) || defined(__PASE__)
1582
  options.gid = -1;
1583
#else
1584
  options.gid = 0;
1585
#endif
1586

1587
  r = uv_spawn(uv_default_loop(), &process, &options);
1588
#if defined(__CYGWIN__) || defined(__MVS__)
1589
  ASSERT_EQ(r, UV_EINVAL);
1590
#else
1591
  ASSERT_EQ(r, UV_EPERM);
1592
#endif
1593

1594
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1595
  ASSERT_OK(r);
1596

1597
  ASSERT_OK(close_cb_called);
1598

1599
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1600
  return 0;
1601
}
1602
#endif
1603

1604

1605
#ifdef _WIN32
1606

1607
static void exit_cb_unexpected(uv_process_t* process,
1608
                               int64_t exit_status,
1609
                               int term_signal) {
1610
  ASSERT(0 && "should not have been called");
1611
}
1612

1613

1614
TEST_IMPL(spawn_setuid_fails) {
1615
  int r;
1616

1617
  init_process_options("spawn_helper1", exit_cb_unexpected);
1618

1619
  options.flags |= UV_PROCESS_SETUID;
1620
  options.uid = (uv_uid_t) -42424242;
1621

1622
  r = uv_spawn(uv_default_loop(), &process, &options);
1623
  ASSERT_EQ(r, UV_ENOTSUP);
1624

1625
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1626
  ASSERT_OK(r);
1627

1628
  ASSERT_OK(close_cb_called);
1629

1630
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1631
  return 0;
1632
}
1633

1634

1635
TEST_IMPL(spawn_setgid_fails) {
1636
  int r;
1637

1638
  init_process_options("spawn_helper1", exit_cb_unexpected);
1639

1640
  options.flags |= UV_PROCESS_SETGID;
1641
  options.gid = (uv_gid_t) -42424242;
1642

1643
  r = uv_spawn(uv_default_loop(), &process, &options);
1644
  ASSERT_EQ(r, UV_ENOTSUP);
1645

1646
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1647
  ASSERT_OK(r);
1648

1649
  ASSERT_OK(close_cb_called);
1650

1651
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1652
  return 0;
1653
}
1654
#endif
1655

1656

1657
TEST_IMPL(spawn_auto_unref) {
1658
  init_process_options("spawn_helper1", NULL);
1659
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
1660
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1661
  ASSERT_OK(uv_is_closing((uv_handle_t*) &process));
1662
  uv_close((uv_handle_t*) &process, NULL);
1663
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1664
  ASSERT_EQ(1, uv_is_closing((uv_handle_t*) &process));
1665
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1666
  return 0;
1667
}
1668

1669

1670
TEST_IMPL(spawn_fs_open) {
1671
  int r;
1672
  uv_os_fd_t fd;
1673
  uv_os_fd_t dup_fd;
1674
  uv_fs_t fs_req;
1675
  uv_pipe_t in;
1676
  uv_write_t write_req;
1677
  uv_write_t write_req2;
1678
  uv_buf_t buf;
1679
  uv_stdio_container_t stdio[1];
1680
#ifdef _WIN32
1681
  const char dev_null[] = "NUL";
1682
  HMODULE kernelbase_module;
1683
  sCompareObjectHandles pCompareObjectHandles; /* function introduced in Windows 10 */
1684
#else
1685
  const char dev_null[] = "/dev/null";
1686
#endif
1687

1688
  r = uv_fs_open(NULL, &fs_req, dev_null, UV_FS_O_RDWR, 0, NULL);
1689
  ASSERT_NE(r, -1);
1690
  fd = uv_get_osfhandle((uv_file) fs_req.result);
1691
  uv_fs_req_cleanup(&fs_req);
1692

1693
  init_process_options("spawn_helper8", exit_cb);
1694

1695
  ASSERT_OK(uv_pipe_init(uv_default_loop(), &in, 0));
1696

1697
  options.stdio = stdio;
1698
  options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
1699
  options.stdio[0].data.stream = (uv_stream_t*) &in;
1700
  options.stdio_count = 1;
1701

1702
  /* make an inheritable copy */
1703
#ifdef _WIN32
1704
  ASSERT_NE(0, DuplicateHandle(GetCurrentProcess(), fd, GetCurrentProcess(), &dup_fd,
1705
                               0, /* inherit */ TRUE, DUPLICATE_SAME_ACCESS));
1706
  kernelbase_module = GetModuleHandleA("kernelbase.dll");
1707
  pCompareObjectHandles = (sCompareObjectHandles)
1708
      GetProcAddress(kernelbase_module, "CompareObjectHandles");
1709
  ASSERT_NE(pCompareObjectHandles == NULL ||
1710
            pCompareObjectHandles(fd, dup_fd),
1711
            0);
1712
#else
1713
  dup_fd = dup(fd);
1714
#endif
1715

1716
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
1717

1718
  buf = uv_buf_init((char*) &fd, sizeof(fd));
1719
  ASSERT_OK(uv_write(&write_req,
1720
                     (uv_stream_t*) &in,
1721
                     &buf,
1722
                     1,
1723
                     write_null_cb));
1724

1725
  buf = uv_buf_init((char*) &dup_fd, sizeof(fd));
1726
  ASSERT_OK(uv_write(&write_req2, (uv_stream_t*) &in, &buf, 1, write_cb));
1727

1728
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
1729
  ASSERT_OK(uv_fs_close(NULL, &fs_req, r, NULL));
1730

1731
  ASSERT_EQ(1, exit_cb_called);
1732
  ASSERT_EQ(2, close_cb_called);  /* One for `in`, one for process */
1733

1734
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1735
  return 0;
1736
}
1737

1738

1739
TEST_IMPL(closed_fd_events) {
1740
  uv_stdio_container_t stdio[3];
1741
  uv_pipe_t pipe_handle;
1742
  uv_fs_t req;
1743
  uv_buf_t bufs[1];
1744
  uv_file fd[2];
1745
  bufs[0] = uv_buf_init("", 1);
1746

1747
  /* create a pipe and share it with a child process */
1748
  ASSERT_OK(uv_pipe(fd, 0, 0));
1749
  ASSERT_GT(fd[0], 2);
1750
  ASSERT_GT(fd[1], 2);
1751

1752
  /* spawn_helper4 blocks indefinitely. */
1753
  init_process_options("spawn_helper4", exit_cb);
1754
  options.stdio_count = 3;
1755
  options.stdio = stdio;
1756
  options.stdio[0].flags = UV_INHERIT_FD;
1757
  options.stdio[0].data.fd = fd[0];
1758
  options.stdio[1].flags = UV_IGNORE;
1759
  options.stdio[2].flags = UV_IGNORE;
1760

1761
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
1762
  uv_unref((uv_handle_t*) &process);
1763

1764
  /* read from the pipe with uv */
1765
  ASSERT_OK(uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
1766
  ASSERT_OK(uv_pipe_open(&pipe_handle, fd[0]));
1767
  /* uv_pipe_open() takes ownership of the file descriptor. */
1768
  fd[0] = -1;
1769

1770
  ASSERT_OK(uv_read_start((uv_stream_t*) &pipe_handle,
1771
                          on_alloc,
1772
                          on_read_once));
1773

1774
  ASSERT_EQ(1, uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL));
1775
  ASSERT_EQ(1, req.result);
1776
  uv_fs_req_cleanup(&req);
1777

1778
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE));
1779

1780
  /* should have received just one byte */
1781
  ASSERT_EQ(1, output_used);
1782

1783
  /* close the pipe and see if we still get events */
1784
  uv_close((uv_handle_t*) &pipe_handle, close_cb);
1785

1786
  ASSERT_EQ(1, uv_fs_write(NULL, &req, fd[1], bufs, 1, -1, NULL));
1787
  ASSERT_EQ(1, req.result);
1788
  uv_fs_req_cleanup(&req);
1789

1790
  ASSERT_OK(uv_timer_init(uv_default_loop(), &timer));
1791
  ASSERT_OK(uv_timer_start(&timer, timer_counter_cb, 10, 0));
1792

1793
  /* see if any spurious events interrupt the timer */
1794
  if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE))
1795
    /* have to run again to really trigger the timer */
1796
    ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_ONCE));
1797

1798
  ASSERT_EQ(1, timer_counter);
1799

1800
  /* cleanup */
1801
  ASSERT_OK(uv_process_kill(&process, SIGTERM));
1802
#ifdef _WIN32
1803
  ASSERT_OK(_close(fd[1]));
1804
#else
1805
  ASSERT_OK(close(fd[1]));
1806
#endif
1807

1808
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1809
  return 0;
1810
}
1811

1812

1813
TEST_IMPL(spawn_reads_child_path) {
1814
  int r;
1815
  int len;
1816
  char file[64];
1817
  char path[1024];
1818
  char* env[3];
1819

1820
  /* Need to carry over the dynamic linker path when the test runner is
1821
   * linked against libuv.so, see https://github.com/libuv/libuv/issues/85.
1822
   */
1823
#if defined(__APPLE__)
1824
  static const char dyld_path_var[] = "DYLD_LIBRARY_PATH";
1825
#elif defined(__MVS__) || defined(__PASE__)
1826
  static const char dyld_path_var[] = "LIBPATH";
1827
#else
1828
  static const char dyld_path_var[] = "LD_LIBRARY_PATH";
1829
#endif
1830

1831
  /* Set up the process, but make sure that the file to run is relative and
1832
   * requires a lookup into PATH. */
1833
  init_process_options("spawn_helper1", exit_cb);
1834

1835
  /* Set up the PATH env variable */
1836
  for (len = strlen(exepath);
1837
       exepath[len - 1] != '/' && exepath[len - 1] != '\\';
1838
       len--);
1839
  strcpy(file, exepath + len);
1840
  exepath[len] = 0;
1841
  strcpy(path, "PATH=");
1842
  strcpy(path + 5, exepath);
1843
#if defined(__CYGWIN__) || defined(__MSYS__)
1844
  /* Carry over the dynamic linker path in case the test runner
1845
     is linked against cyguv-1.dll or msys-uv-1.dll, see above.  */
1846
  {
1847
    char* syspath = getenv("PATH");
1848
    if (syspath != NULL) {
1849
      strcat(path, ":");
1850
      strcat(path, syspath);
1851
    }
1852
  }
1853
#endif
1854

1855
  env[0] = path;
1856
  env[1] = getenv(dyld_path_var);
1857
  env[2] = NULL;
1858

1859
  if (env[1] != NULL) {
1860
    static char buf[1024 + sizeof(dyld_path_var)];
1861
    snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]);
1862
    env[1] = buf;
1863
  }
1864

1865
  options.file = file;
1866
  options.args[0] = file;
1867
  options.env = env;
1868

1869
  r = uv_spawn(uv_default_loop(), &process, &options);
1870
  ASSERT_OK(r);
1871

1872
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
1873
  ASSERT_OK(r);
1874

1875
  ASSERT_EQ(1, exit_cb_called);
1876
  ASSERT_EQ(1, close_cb_called);
1877

1878
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1879
  return 0;
1880
}
1881

1882
TEST_IMPL(spawn_inherit_streams) {
1883
  uv_process_t child_req;
1884
  uv_stdio_container_t child_stdio[2];
1885
  int fds_stdin[2];
1886
  int fds_stdout[2];
1887
  uv_pipe_t pipe_stdin_child;
1888
  uv_pipe_t pipe_stdout_child;
1889
  uv_pipe_t pipe_stdin_parent;
1890
  uv_pipe_t pipe_stdout_parent;
1891
  unsigned char ubuf[OUTPUT_SIZE - 1];
1892
  uv_buf_t buf;
1893
  unsigned int i;
1894
  int r;
1895
  int bidir;
1896
  uv_write_t write_req;
1897
  uv_loop_t* loop;
1898

1899
  init_process_options("spawn_helper9", exit_cb);
1900

1901
  loop = uv_default_loop();
1902
  ASSERT_OK(uv_pipe_init(loop, &pipe_stdin_child, 0));
1903
  ASSERT_OK(uv_pipe_init(loop, &pipe_stdout_child, 0));
1904
  ASSERT_OK(uv_pipe_init(loop, &pipe_stdin_parent, 0));
1905
  ASSERT_OK(uv_pipe_init(loop, &pipe_stdout_parent, 0));
1906

1907
  ASSERT_OK(uv_pipe(fds_stdin, 0, 0));
1908
  ASSERT_OK(uv_pipe(fds_stdout, 0, 0));
1909

1910
  ASSERT_OK(uv_pipe_open(&pipe_stdin_child, fds_stdin[0]));
1911
  ASSERT_OK(uv_pipe_open(&pipe_stdout_child, fds_stdout[1]));
1912
  ASSERT_OK(uv_pipe_open(&pipe_stdin_parent, fds_stdin[1]));
1913
  ASSERT_OK(uv_pipe_open(&pipe_stdout_parent, fds_stdout[0]));
1914
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdin_child));
1915
  ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdout_child));
1916
  ASSERT(uv_is_writable((uv_stream_t*) &pipe_stdin_parent));
1917
  ASSERT(uv_is_readable((uv_stream_t*) &pipe_stdout_parent));
1918
  /* Some systems (SVR4) open a bidirectional pipe, most don't. */
1919
  bidir = uv_is_writable((uv_stream_t*) &pipe_stdin_child);
1920
  ASSERT_EQ(uv_is_readable((uv_stream_t*) &pipe_stdout_child), bidir);
1921
  ASSERT_EQ(uv_is_readable((uv_stream_t*) &pipe_stdin_parent), bidir);
1922
  ASSERT_EQ(uv_is_writable((uv_stream_t*) &pipe_stdout_parent), bidir);
1923

1924
  child_stdio[0].flags = UV_INHERIT_STREAM;
1925
  child_stdio[0].data.stream = (uv_stream_t *) &pipe_stdin_child;
1926

1927
  child_stdio[1].flags = UV_INHERIT_STREAM;
1928
  child_stdio[1].data.stream = (uv_stream_t *) &pipe_stdout_child;
1929

1930
  options.stdio = child_stdio;
1931
  options.stdio_count = 2;
1932

1933
  ASSERT_OK(uv_spawn(loop, &child_req, &options));
1934

1935
  uv_close((uv_handle_t*) &pipe_stdin_child, NULL);
1936
  uv_close((uv_handle_t*) &pipe_stdout_child, NULL);
1937

1938
  buf = uv_buf_init((char*) ubuf, sizeof ubuf);
1939
  for (i = 0; i < sizeof ubuf; ++i)
1940
    ubuf[i] = i & 255u;
1941
  memset(output, 0, sizeof ubuf);
1942

1943
  r = uv_write(&write_req,
1944
               (uv_stream_t*) &pipe_stdin_parent,
1945
               &buf,
1946
               1,
1947
               write_cb);
1948
  ASSERT_OK(r);
1949

1950
  r = uv_read_start((uv_stream_t*) &pipe_stdout_parent, on_alloc, on_read);
1951
  ASSERT_OK(r);
1952

1953
  r = uv_run(loop, UV_RUN_DEFAULT);
1954
  ASSERT_OK(r);
1955

1956
  ASSERT_EQ(1, exit_cb_called);
1957
  ASSERT_EQ(3, close_cb_called);
1958

1959
  r = memcmp(ubuf, output, sizeof ubuf);
1960
  ASSERT_OK(r);
1961

1962
  MAKE_VALGRIND_HAPPY(loop);
1963
  return 0;
1964
}
1965

1966
TEST_IMPL(spawn_quoted_path) {
1967
#ifndef _WIN32
1968
  RETURN_SKIP("Test for Windows");
1969
#else
1970
  char* quoted_path_env[2];
1971
  args[0] = "not_existing";
1972
  args[1] = NULL;
1973
  options.file = args[0];
1974
  options.args = args;
1975
  options.exit_cb = exit_cb;
1976
  options.flags = 0;
1977
  /* We test if search_path works correctly with semicolons in quoted path. We
1978
   * will use an invalid drive, so we are sure no executable is spawned. */
1979
  quoted_path_env[0] = "PATH=\"xyz:\\test;\";xyz:\\other";
1980
  quoted_path_env[1] = NULL;
1981
  options.env = quoted_path_env;
1982

1983
  /* We test if libuv will not segfault. */
1984
  uv_spawn(uv_default_loop(), &process, &options);
1985

1986
  MAKE_VALGRIND_HAPPY(uv_default_loop());
1987
  return 0;
1988
#endif
1989
}
1990

1991
TEST_IMPL(spawn_exercise_sigchld_issue) {
1992
  int r;
1993
  int i;
1994
  uv_process_options_t dummy_options = {0};
1995
  uv_process_t dummy_processes[100];
1996
  char* args[2];
1997

1998
  init_process_options("spawn_helper1", exit_cb);
1999

2000
  r = uv_spawn(uv_default_loop(), &process, &options);
2001
  ASSERT_OK(r);
2002

2003
  // This test exercises a bug in the darwin kernel that causes SIGCHLD not to
2004
  // be delivered sometimes. Calling posix_spawn many times increases the
2005
  // likelihood of encountering this issue, so spin a few times to make this
2006
  // test more reliable.
2007
  dummy_options.file = args[0] = "program-that-had-better-not-exist";
2008
  args[1] = NULL;
2009
  dummy_options.args = args;
2010
  dummy_options.exit_cb = fail_cb;
2011
  dummy_options.flags = 0;
2012
  for (i = 0; i < 100; i++) {
2013
    r = uv_spawn(uv_default_loop(), &dummy_processes[i], &dummy_options);
2014
    if (r != UV_ENOENT)
2015
      ASSERT_EQ(r, UV_EACCES);
2016
    uv_close((uv_handle_t*) &dummy_processes[i], close_cb);
2017
  }
2018

2019
  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
2020
  ASSERT_OK(r);
2021

2022
  ASSERT_EQ(1, exit_cb_called);
2023
  ASSERT_EQ(101, close_cb_called);
2024

2025
  MAKE_VALGRIND_HAPPY(uv_default_loop());
2026
  return 0;
2027
}
2028

2029
/* Helper for child process of spawn_inherit_streams */
2030
#ifndef _WIN32
2031
void spawn_stdin_stdout(void) {
2032
  char buf[1024];
2033
  char* pbuf;
2034
  for (;;) {
2035
    ssize_t r, w, c;
2036
    do {
2037
      r = read(0, buf, sizeof buf);
2038
    } while (r == -1 && errno == EINTR);
2039
    if (r == 0) {
2040
      return;
2041
    }
2042
    ASSERT_GT(r, 0);
2043
    c = r;
2044
    pbuf = buf;
2045
    while (c) {
2046
      do {
2047
        w = write(1, pbuf, (size_t)c);
2048
      } while (w == -1 && errno == EINTR);
2049
      ASSERT_GE(w, 0);
2050
      pbuf = pbuf + w;
2051
      c = c - w;
2052
    }
2053
  }
2054
}
2055
#else
2056
void spawn_stdin_stdout(void) {
2057
  char buf[1024];
2058
  char* pbuf;
2059
  HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
2060
  HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
2061
  ASSERT_PTR_NE(h_stdin, INVALID_HANDLE_VALUE);
2062
  ASSERT_PTR_NE(h_stdout, INVALID_HANDLE_VALUE);
2063
  for (;;) {
2064
    DWORD n_read;
2065
    DWORD n_written;
2066
    DWORD to_write;
2067
    if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
2068
      ASSERT_EQ(GetLastError(), ERROR_BROKEN_PIPE);
2069
      return;
2070
    }
2071
    to_write = n_read;
2072
    pbuf = buf;
2073
    while (to_write) {
2074
      ASSERT(WriteFile(h_stdout, pbuf, to_write, &n_written, NULL));
2075
      to_write -= n_written;
2076
      pbuf += n_written;
2077
    }
2078
  }
2079
}
2080
#endif /* !_WIN32 */
2081

2082
TEST_IMPL(spawn_relative_path) {
2083
  char* sep;
2084

2085
  init_process_options("spawn_helper1", exit_cb);
2086

2087
  exepath_size = sizeof(exepath) - 2;
2088
  ASSERT_OK(uv_exepath(exepath, &exepath_size));
2089
  exepath[exepath_size] = '\0';
2090

2091
  /* Poor man's basename(3). */
2092
  sep = strrchr(exepath, '/');
2093
  if (sep == NULL)
2094
    sep = strrchr(exepath, '\\');
2095
  ASSERT_NOT_NULL(sep);
2096

2097
  /* Split into dirname and basename and make basename relative. */
2098
  memmove(sep + 2, sep, 1 + strlen(sep));
2099
  sep[0] = '\0';
2100
  sep[1] = '.';
2101
  sep[2] = '/';
2102

2103
  options.cwd = exepath;
2104
  options.file = options.args[0] = sep + 1;
2105

2106
  ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
2107
  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
2108

2109
  ASSERT_EQ(1, exit_cb_called);
2110
  ASSERT_EQ(1, close_cb_called);
2111

2112
  MAKE_VALGRIND_HAPPY(uv_default_loop());
2113
  return 0;
2114
}
2115

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.