GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/spawn_sync.cc Lines: 462 505 91.5 %
Date: 2017-06-14 Branches: 212 320 66.3 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "spawn_sync.h"
23
#include "env-inl.h"
24
#include "string_bytes.h"
25
#include "util.h"
26
27
#include <string.h>
28
#include <stdlib.h>
29
30
31
namespace node {
32
33
using v8::Array;
34
using v8::Context;
35
using v8::EscapableHandleScope;
36
using v8::FunctionCallbackInfo;
37
using v8::HandleScope;
38
using v8::Integer;
39
using v8::Isolate;
40
using v8::Local;
41
using v8::Null;
42
using v8::Number;
43
using v8::Object;
44
using v8::String;
45
using v8::Value;
46
47
48
348
SyncProcessOutputBuffer::SyncProcessOutputBuffer()
49
    : used_(0),
50
348
      next_(nullptr) {
51
348
}
52
53
54
823
void SyncProcessOutputBuffer::OnAlloc(size_t suggested_size,
55
                                      uv_buf_t* buf) const {
56
823
  if (used() == kBufferSize)
57
    *buf = uv_buf_init(nullptr, 0);
58
  else
59
823
    *buf = uv_buf_init(data_ + used(), available());
60
823
}
61
62
63
485
void SyncProcessOutputBuffer::OnRead(const uv_buf_t* buf, size_t nread) {
64
  // If we hand out the same chunk twice, this should catch it.
65
485
  CHECK_EQ(buf->base, data_ + used());
66
485
  used_ += static_cast<unsigned int>(nread);
67
485
}
68
69
70
348
size_t SyncProcessOutputBuffer::Copy(char* dest) const {
71
348
  memcpy(dest, data_, used());
72
348
  return used();
73
}
74
75
76
1301
unsigned int SyncProcessOutputBuffer::available() const {
77
1301
  return sizeof data_ - used();
78
}
79
80
81
4476
unsigned int SyncProcessOutputBuffer::used() const {
82
4476
  return used_;
83
}
84
85
86
1044
SyncProcessOutputBuffer* SyncProcessOutputBuffer::next() const {
87
1044
  return next_;
88
}
89
90
91
3
void SyncProcessOutputBuffer::set_next(SyncProcessOutputBuffer* next) {
92
3
  next_ = next;
93
3
}
94
95
96
1764
SyncProcessStdioPipe::SyncProcessStdioPipe(SyncProcessRunner* process_handler,
97
                                           bool readable,
98
                                           bool writable,
99
                                           uv_buf_t input_buffer)
100
    : process_handler_(process_handler),
101
      readable_(readable),
102
      writable_(writable),
103
      input_buffer_(input_buffer),
104
105
      first_output_buffer_(nullptr),
106
      last_output_buffer_(nullptr),
107
108
      uv_pipe_(),
109
      write_req_(),
110
      shutdown_req_(),
111
112
1764
      lifecycle_(kUninitialized) {
113

1764
  CHECK(readable || writable);
114
1764
}
115
116
117
1764
SyncProcessStdioPipe::~SyncProcessStdioPipe() {
118

1764
  CHECK(lifecycle_ == kUninitialized || lifecycle_ == kClosed);
119
120
  SyncProcessOutputBuffer* buf;
121
  SyncProcessOutputBuffer* next;
122
123
2112
  for (buf = first_output_buffer_; buf != nullptr; buf = next) {
124
348
    next = buf->next();
125
348
    delete buf;
126
  }
127
1764
}
128
129
130
1764
int SyncProcessStdioPipe::Initialize(uv_loop_t* loop) {
131
1764
  CHECK_EQ(lifecycle_, kUninitialized);
132
133
1764
  int r = uv_pipe_init(loop, uv_pipe(), 0);
134
1764
  if (r < 0)
135
    return r;
136
137
1764
  uv_pipe()->data = this;
138
139
1764
  lifecycle_ = kInitialized;
140
1764
  return 0;
141
}
142
143
144
534
int SyncProcessStdioPipe::Start() {
145
534
  CHECK_EQ(lifecycle_, kInitialized);
146
147
  // Set the busy flag already. If this function fails no recovery is
148
  // possible.
149
534
  lifecycle_ = kStarted;
150
151
534
  if (readable()) {
152
178
    if (input_buffer_.len > 0) {
153
7
      CHECK_NE(input_buffer_.base, nullptr);
154
155
      int r = uv_write(&write_req_,
156
                       uv_stream(),
157
                       &input_buffer_,
158
                       1,
159
7
                       WriteCallback);
160
7
      if (r < 0)
161
        return r;
162
    }
163
164
178
    int r = uv_shutdown(&shutdown_req_, uv_stream(), ShutdownCallback);
165
178
    if (r < 0)
166
      return r;
167
  }
168
169
534
  if (writable()) {
170
356
    int r = uv_read_start(uv_stream(), AllocCallback, ReadCallback);
171
356
    if (r < 0)
172
      return r;
173
  }
174
175
534
  return 0;
176
}
177
178
179
1764
void SyncProcessStdioPipe::Close() {
180

1764
  CHECK(lifecycle_ == kInitialized || lifecycle_ == kStarted);
181
182
1764
  uv_close(uv_handle(), CloseCallback);
183
184
1764
  lifecycle_ = kClosing;
185
1764
}
186
187
188
356
Local<Object> SyncProcessStdioPipe::GetOutputAsBuffer(Environment* env) const {
189
356
  size_t length = OutputLength();
190
712
  Local<Object> js_buffer = Buffer::New(env, length).ToLocalChecked();
191
356
  CopyOutput(Buffer::Data(js_buffer));
192
356
  return js_buffer;
193
}
194
195
196
2298
bool SyncProcessStdioPipe::readable() const {
197
2298
  return readable_;
198
}
199
200
201
2832
bool SyncProcessStdioPipe::writable() const {
202
2832
  return writable_;
203
}
204
205
206
1764
uv_stdio_flags SyncProcessStdioPipe::uv_flags() const {
207
  unsigned int flags;
208
209
1764
  flags = UV_CREATE_PIPE;
210
1764
  if (readable())
211
588
    flags |= UV_READABLE_PIPE;
212
1764
  if (writable())
213
1176
    flags |= UV_WRITABLE_PIPE;
214
215
1764
  return static_cast<uv_stdio_flags>(flags);
216
}
217
218
219
7597
uv_pipe_t* SyncProcessStdioPipe::uv_pipe() const {
220
7597
  CHECK_LT(lifecycle_, kClosing);
221
7597
  return &uv_pipe_;
222
}
223
224
225
2305
uv_stream_t* SyncProcessStdioPipe::uv_stream() const {
226
2305
  return reinterpret_cast<uv_stream_t*>(uv_pipe());
227
}
228
229
230
1764
uv_handle_t* SyncProcessStdioPipe::uv_handle() const {
231
1764
  return reinterpret_cast<uv_handle_t*>(uv_pipe());
232
}
233
234
235
356
size_t SyncProcessStdioPipe::OutputLength() const {
236
  SyncProcessOutputBuffer* buf;
237
356
  size_t size = 0;
238
239
704
  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
240
348
    size += buf->used();
241
242
356
  return size;
243
}
244
245
246
356
void SyncProcessStdioPipe::CopyOutput(char* dest) const {
247
  SyncProcessOutputBuffer* buf;
248
356
  size_t offset = 0;
249
250
704
  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
251
348
    offset += buf->Copy(dest + offset);
252
356
}
253
254
255
823
void SyncProcessStdioPipe::OnAlloc(size_t suggested_size, uv_buf_t* buf) {
256
  // This function assumes that libuv will never allocate two buffers for the
257
  // same stream at the same time. There's an assert in
258
  // SyncProcessOutputBuffer::OnRead that would fail if this assumption was
259
  // ever violated.
260
261
823
  if (last_output_buffer_ == nullptr) {
262
    // Allocate the first capture buffer.
263
345
    first_output_buffer_ = new SyncProcessOutputBuffer();
264
345
    last_output_buffer_ = first_output_buffer_;
265
266
478
  } else if (last_output_buffer_->available() == 0) {
267
    // The current capture buffer is full so get us a new one.
268
3
    SyncProcessOutputBuffer* buf = new SyncProcessOutputBuffer();
269
3
    last_output_buffer_->set_next(buf);
270
3
    last_output_buffer_ = buf;
271
  }
272
273
823
  last_output_buffer_->OnAlloc(suggested_size, buf);
274
823
}
275
276
277
829
void SyncProcessStdioPipe::OnRead(const uv_buf_t* buf, ssize_t nread) {
278
829
  if (nread == UV_EOF) {
279
    // Libuv implicitly stops reading on EOF.
280
281
485
  } else if (nread < 0) {
282
    SetError(static_cast<int>(nread));
283
    // At some point libuv should really implicitly stop reading on error.
284
    uv_read_stop(uv_stream());
285
286
  } else {
287
485
    last_output_buffer_->OnRead(buf, nread);
288
485
    process_handler_->IncrementBufferSizeAndCheckOverflow(nread);
289
  }
290
829
}
291
292
293
7
void SyncProcessStdioPipe::OnWriteDone(int result) {
294
7
  if (result < 0)
295
    SetError(result);
296
7
}
297
298
299
178
void SyncProcessStdioPipe::OnShutdownDone(int result) {
300
178
  if (result < 0)
301
    SetError(result);
302
178
}
303
304
305
1764
void SyncProcessStdioPipe::OnClose() {
306
1764
  lifecycle_ = kClosed;
307
1764
}
308
309
310
void SyncProcessStdioPipe::SetError(int error) {
311
  CHECK_NE(error, 0);
312
  process_handler_->SetPipeError(error);
313
}
314
315
316
823
void SyncProcessStdioPipe::AllocCallback(uv_handle_t* handle,
317
                                         size_t suggested_size,
318
                                         uv_buf_t* buf) {
319
  SyncProcessStdioPipe* self =
320
823
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
321
823
  self->OnAlloc(suggested_size, buf);
322
823
}
323
324
325
829
void SyncProcessStdioPipe::ReadCallback(uv_stream_t* stream,
326
                                        ssize_t nread,
327
                                        const uv_buf_t* buf) {
328
  SyncProcessStdioPipe* self =
329
829
        reinterpret_cast<SyncProcessStdioPipe*>(stream->data);
330
829
  self->OnRead(buf, nread);
331
829
}
332
333
334
7
void SyncProcessStdioPipe::WriteCallback(uv_write_t* req, int result) {
335
  SyncProcessStdioPipe* self =
336
7
      reinterpret_cast<SyncProcessStdioPipe*>(req->handle->data);
337
7
  self->OnWriteDone(result);
338
7
}
339
340
341
178
void SyncProcessStdioPipe::ShutdownCallback(uv_shutdown_t* req, int result) {
342
  SyncProcessStdioPipe* self =
343
178
      reinterpret_cast<SyncProcessStdioPipe*>(req->handle->data);
344
345
  // On AIX, OS X and the BSDs, calling shutdown() on one end of a pipe
346
  // when the other end has closed the connection fails with ENOTCONN.
347
  // Libuv is not the right place to handle that because it can't tell
348
  // if the error is genuine but we here can.
349
178
  if (result == UV_ENOTCONN)
350
    result = 0;
351
352
178
  self->OnShutdownDone(result);
353
178
}
354
355
356
1764
void SyncProcessStdioPipe::CloseCallback(uv_handle_t* handle) {
357
  SyncProcessStdioPipe* self =
358
1764
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
359
1764
  self->OnClose();
360
1764
}
361
362
363
2172
void SyncProcessRunner::Initialize(Local<Object> target,
364
                                   Local<Value> unused,
365
                                   Local<Context> context) {
366
2172
  Environment* env = Environment::GetCurrent(context);
367
2172
  env->SetMethod(target, "spawn", Spawn);
368
2172
}
369
370
371
592
void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
372
592
  Environment* env = Environment::GetCurrent(args);
373
592
  env->PrintSyncTrace();
374
592
  SyncProcessRunner p(env);
375
592
  Local<Value> result = p.Run(args[0]);
376
1184
  args.GetReturnValue().Set(result);
377
592
}
378
379
380
592
SyncProcessRunner::SyncProcessRunner(Environment* env)
381
    : max_buffer_(0),
382
      timeout_(0),
383
      kill_signal_(SIGTERM),
384
385
      uv_loop_(nullptr),
386
387
      stdio_count_(0),
388
      uv_stdio_containers_(nullptr),
389
      stdio_pipes_(nullptr),
390
      stdio_pipes_initialized_(false),
391
392
      uv_process_options_(),
393
      file_buffer_(nullptr),
394
      args_buffer_(nullptr),
395
      env_buffer_(nullptr),
396
      cwd_buffer_(nullptr),
397
398
      uv_process_(),
399
      killed_(false),
400
401
      buffered_output_size_(0),
402
      exit_status_(-1),
403
      term_signal_(-1),
404
405
      uv_timer_(),
406
      kill_timer_initialized_(false),
407
408
      error_(0),
409
      pipe_error_(0),
410
411
      lifecycle_(kUninitialized),
412
413
592
      env_(env) {
414
592
}
415
416
417
592
SyncProcessRunner::~SyncProcessRunner() {
418
592
  CHECK_EQ(lifecycle_, kHandlesClosed);
419
420
592
  if (stdio_pipes_ != nullptr) {
421
2368
    for (size_t i = 0; i < stdio_count_; i++) {
422
1776
      if (stdio_pipes_[i] != nullptr)
423
1764
        delete stdio_pipes_[i];
424
    }
425
  }
426
427
592
  delete[] stdio_pipes_;
428
592
  delete[] file_buffer_;
429
592
  delete[] args_buffer_;
430
592
  delete[] cwd_buffer_;
431
592
  delete[] env_buffer_;
432
592
  delete[] uv_stdio_containers_;
433
592
}
434
435
436
27615
Environment* SyncProcessRunner::env() const {
437
27615
  return env_;
438
}
439
440
441
592
Local<Object> SyncProcessRunner::Run(Local<Value> options) {
442
592
  EscapableHandleScope scope(env()->isolate());
443
444
592
  CHECK_EQ(lifecycle_, kUninitialized);
445
446
592
  TryInitializeAndRunLoop(options);
447
592
  CloseHandlesAndDeleteLoop();
448
449
592
  Local<Object> result = BuildResultObject();
450
451
592
  return scope.Escape(result);
452
}
453
454
455
592
void SyncProcessRunner::TryInitializeAndRunLoop(Local<Value> options) {
456
  int r;
457
458
  // There is no recovery from failure inside TryInitializeAndRunLoop - the
459
  // only option we'd have is to close all handles and destroy the loop.
460
592
  CHECK_EQ(lifecycle_, kUninitialized);
461
592
  lifecycle_ = kInitialized;
462
463
592
  uv_loop_ = new uv_loop_t;
464
592
  if (uv_loop_ == nullptr)
465
    return SetError(UV_ENOMEM);
466
592
  CHECK_EQ(uv_loop_init(uv_loop_), 0);
467
468
592
  r = ParseOptions(options);
469
592
  if (r < 0)
470
    return SetError(r);
471
472
592
  if (timeout_ > 0) {
473
6
    r = uv_timer_init(uv_loop_, &uv_timer_);
474
6
    if (r < 0)
475
      return SetError(r);
476
477
6
    uv_unref(reinterpret_cast<uv_handle_t*>(&uv_timer_));
478
479
6
    uv_timer_.data = this;
480
6
    kill_timer_initialized_ = true;
481
482
    // Start the timer immediately. If uv_spawn fails then
483
    // CloseHandlesAndDeleteLoop() will immediately close the timer handle
484
    // which implicitly stops it, so there is no risk that the timeout callback
485
    // runs when the process didn't start.
486
6
    r = uv_timer_start(&uv_timer_, KillTimerCallback, timeout_, 0);
487
6
    if (r < 0)
488
      return SetError(r);
489
  }
490
491
592
  uv_process_options_.exit_cb = ExitCallback;
492
592
  r = uv_spawn(uv_loop_, &uv_process_, &uv_process_options_);
493
592
  if (r < 0)
494
410
    return SetError(r);
495
182
  uv_process_.data = this;
496
497
728
  for (uint32_t i = 0; i < stdio_count_; i++) {
498
546
    SyncProcessStdioPipe* h = stdio_pipes_[i];
499
546
    if (h != nullptr) {
500
534
      r = h->Start();
501
534
      if (r < 0)
502
        return SetPipeError(r);
503
    }
504
  }
505
506
182
  r = uv_run(uv_loop_, UV_RUN_DEFAULT);
507
182
  if (r < 0)
508
    // We can't handle uv_run failure.
509
    ABORT();
510
511
  // If we get here the process should have exited.
512
182
  CHECK_GE(exit_status_, 0);
513
}
514
515
516
592
void SyncProcessRunner::CloseHandlesAndDeleteLoop() {
517
592
  CHECK_LT(lifecycle_, kHandlesClosed);
518
519
592
  if (uv_loop_ != nullptr) {
520
592
    CloseStdioPipes();
521
592
    CloseKillTimer();
522
    // Close the process handle when ExitCallback was not called.
523
    uv_handle_t* uv_process_handle =
524
592
        reinterpret_cast<uv_handle_t*>(&uv_process_);
525
526
    // Close the process handle if it is still open. The handle type also
527
    // needs to be checked because TryInitializeAndRunLoop() won't spawn a
528
    // process if input validation fails.
529

1184
    if (uv_process_handle->type == UV_PROCESS &&
530
592
        !uv_is_closing(uv_process_handle))
531
410
      uv_close(uv_process_handle, nullptr);
532
533
    // Give closing watchers a chance to finish closing and get their close
534
    // callbacks called.
535
592
    int r = uv_run(uv_loop_, UV_RUN_DEFAULT);
536
592
    if (r < 0)
537
      ABORT();
538
539
592
    CHECK_EQ(uv_loop_close(uv_loop_), 0);
540
592
    delete uv_loop_;
541
592
    uv_loop_ = nullptr;
542
543
  } else {
544
    // If the loop doesn't exist, neither should any pipes or timers.
545
    CHECK_EQ(false, stdio_pipes_initialized_);
546
    CHECK_EQ(false, kill_timer_initialized_);
547
  }
548
549
592
  lifecycle_ = kHandlesClosed;
550
592
}
551
552
553
598
void SyncProcessRunner::CloseStdioPipes() {
554
598
  CHECK_LT(lifecycle_, kHandlesClosed);
555
556
598
  if (stdio_pipes_initialized_) {
557
592
    CHECK_NE(stdio_pipes_, nullptr);
558
592
    CHECK_NE(uv_loop_, nullptr);
559
560
2368
    for (uint32_t i = 0; i < stdio_count_; i++) {
561
1776
      if (stdio_pipes_[i] != nullptr)
562
1764
        stdio_pipes_[i]->Close();
563
    }
564
565
592
    stdio_pipes_initialized_ = false;
566
  }
567
598
}
568
569
570
598
void SyncProcessRunner::CloseKillTimer() {
571
598
  CHECK_LT(lifecycle_, kHandlesClosed);
572
573
598
  if (kill_timer_initialized_) {
574
6
    CHECK_GT(timeout_, 0);
575
6
    CHECK_NE(uv_loop_, nullptr);
576
577
6
    uv_handle_t* uv_timer_handle = reinterpret_cast<uv_handle_t*>(&uv_timer_);
578
6
    uv_ref(uv_timer_handle);
579
6
    uv_close(uv_timer_handle, KillTimerCloseCallback);
580
581
6
    kill_timer_initialized_ = false;
582
  }
583
598
}
584
585
586
6
void SyncProcessRunner::Kill() {
587
  // Only attempt to kill once.
588
6
  if (killed_)
589
6
    return;
590
6
  killed_ = true;
591
592
  // We might get here even if the process we spawned has already exited. This
593
  // could happen when our child process spawned another process which
594
  // inherited (one of) the stdio pipes. In this case we won't attempt to send
595
  // a signal to the process, however we will still close our end of the stdio
596
  // pipes so this situation won't make us hang.
597
6
  if (exit_status_ < 0) {
598
6
    int r = uv_process_kill(&uv_process_, kill_signal_);
599
600
    // If uv_kill failed with an error that isn't ESRCH, the user probably
601
    // specified an invalid or unsupported signal. Signal this to the user as
602
    // and error and kill the process with SIGKILL instead.
603

6
    if (r < 0 && r != UV_ESRCH) {
604
      SetError(r);
605
606
      r = uv_process_kill(&uv_process_, SIGKILL);
607
      CHECK(r >= 0 || r == UV_ESRCH);
608
    }
609
  }
610
611
  // Close all stdio pipes.
612
6
  CloseStdioPipes();
613
614
  // Stop the timeout timer immediately.
615
6
  CloseKillTimer();
616
}
617
618
619
485
void SyncProcessRunner::IncrementBufferSizeAndCheckOverflow(ssize_t length) {
620
485
  buffered_output_size_ += length;
621
622

485
  if (max_buffer_ > 0 && buffered_output_size_ > max_buffer_) {
623
1
    SetError(UV_ENOBUFS);
624
1
    Kill();
625
  }
626
485
}
627
628
629
182
void SyncProcessRunner::OnExit(int64_t exit_status, int term_signal) {
630
182
  if (exit_status < 0)
631
182
    return SetError(static_cast<int>(exit_status));
632
633
182
  exit_status_ = exit_status;
634
182
  term_signal_ = term_signal;
635
}
636
637
638
5
void SyncProcessRunner::OnKillTimerTimeout() {
639
5
  SetError(UV_ETIMEDOUT);
640
5
  Kill();
641
5
}
642
643
644
1008
int SyncProcessRunner::GetError() {
645
1008
  if (error_ != 0)
646
832
    return error_;
647
  else
648
176
    return pipe_error_;
649
}
650
651
652
416
void SyncProcessRunner::SetError(int error) {
653
416
  if (error_ == 0)
654
416
    error_ = error;
655
416
}
656
657
658
void SyncProcessRunner::SetPipeError(int pipe_error) {
659
  if (pipe_error_ == 0)
660
    pipe_error_ = pipe_error;
661
}
662
663
664
592
Local<Object> SyncProcessRunner::BuildResultObject() {
665
592
  EscapableHandleScope scope(env()->isolate());
666
667
592
  Local<Object> js_result = Object::New(env()->isolate());
668
669
592
  if (GetError() != 0) {
670
    js_result->Set(env()->error_string(),
671
1248
                   Integer::New(env()->isolate(), GetError()));
672
  }
673
674
592
  if (exit_status_ >= 0) {
675
182
    if (term_signal_ > 0) {
676
21
      js_result->Set(env()->status_string(), Null(env()->isolate()));
677
    } else {
678
      js_result->Set(env()->status_string(),
679
525
          Number::New(env()->isolate(), static_cast<double>(exit_status_)));
680
    }
681
  } else {
682
    // If exit_status_ < 0 the process was never started because of some error.
683
1230
    js_result->Set(env()->status_string(), Null(env()->isolate()));
684
  }
685
686
592
  if (term_signal_ > 0)
687
    js_result->Set(env()->signal_string(),
688
21
        String::NewFromUtf8(env()->isolate(), signo_string(term_signal_)));
689
  else
690
1755
    js_result->Set(env()->signal_string(), Null(env()->isolate()));
691
692
592
  if (exit_status_ >= 0)
693
546
    js_result->Set(env()->output_string(), BuildOutputArray());
694
  else
695
1230
    js_result->Set(env()->output_string(), Null(env()->isolate()));
696
697
  js_result->Set(env()->pid_string(),
698
1776
                 Number::New(env()->isolate(), uv_process_.pid));
699
700
592
  return scope.Escape(js_result);
701
}
702
703
704
182
Local<Array> SyncProcessRunner::BuildOutputArray() {
705
182
  CHECK_GE(lifecycle_, kInitialized);
706
182
  CHECK_NE(stdio_pipes_, nullptr);
707
708
182
  EscapableHandleScope scope(env()->isolate());
709
182
  Local<Array> js_output = Array::New(env()->isolate(), stdio_count_);
710
711
728
  for (uint32_t i = 0; i < stdio_count_; i++) {
712
546
    SyncProcessStdioPipe* h = stdio_pipes_[i];
713

546
    if (h != nullptr && h->writable())
714
712
      js_output->Set(i, h->GetOutputAsBuffer(env()));
715
    else
716
380
      js_output->Set(i, Null(env()->isolate()));
717
  }
718
719
182
  return scope.Escape(js_output);
720
}
721
722
723
592
int SyncProcessRunner::ParseOptions(Local<Value> js_value) {
724
592
  HandleScope scope(env()->isolate());
725
  int r;
726
727
592
  if (!js_value->IsObject())
728
    return UV_EINVAL;
729
730
592
  Local<Object> js_options = js_value.As<Object>();
731
732
1184
  Local<Value> js_file = js_options->Get(env()->file_string());
733
592
  r = CopyJsString(js_file, &file_buffer_);
734
592
  if (r < 0)
735
    return r;
736
592
  uv_process_options_.file = file_buffer_;
737
738
1184
  Local<Value> js_args = js_options->Get(env()->args_string());
739
592
  r = CopyJsStringArray(js_args, &args_buffer_);
740
592
  if (r < 0)
741
    return r;
742
592
  uv_process_options_.args = reinterpret_cast<char**>(args_buffer_);
743
744
745
1184
  Local<Value> js_cwd = js_options->Get(env()->cwd_string());
746
592
  if (IsSet(js_cwd)) {
747
22
    r = CopyJsString(js_cwd, &cwd_buffer_);
748
22
    if (r < 0)
749
      return r;
750
22
    uv_process_options_.cwd = cwd_buffer_;
751
  }
752
753
1184
  Local<Value> js_env_pairs = js_options->Get(env()->env_pairs_string());
754
592
  if (IsSet(js_env_pairs)) {
755
592
    r = CopyJsStringArray(js_env_pairs, &env_buffer_);
756
592
    if (r < 0)
757
      return r;
758
759
592
    uv_process_options_.env = reinterpret_cast<char**>(env_buffer_);
760
  }
761
1184
  Local<Value> js_uid = js_options->Get(env()->uid_string());
762
592
  if (IsSet(js_uid)) {
763
1
    CHECK(js_uid->IsInt32());
764
3
    const int32_t uid = js_uid->Int32Value(env()->context()).FromJust();
765
1
    uv_process_options_.uid = static_cast<uv_uid_t>(uid);
766
1
    uv_process_options_.flags |= UV_PROCESS_SETUID;
767
  }
768
769
1184
  Local<Value> js_gid = js_options->Get(env()->gid_string());
770
592
  if (IsSet(js_gid)) {
771
1
    CHECK(js_gid->IsInt32());
772
3
    const int32_t gid = js_gid->Int32Value(env()->context()).FromJust();
773
1
    uv_process_options_.gid = static_cast<uv_gid_t>(gid);
774
1
    uv_process_options_.flags |= UV_PROCESS_SETGID;
775
  }
776
777
1776
  if (js_options->Get(env()->detached_string())->BooleanValue())
778
1
    uv_process_options_.flags |= UV_PROCESS_DETACHED;
779
780
592
  Local<String> wba = env()->windows_verbatim_arguments_string();
781
782
1184
  if (js_options->Get(wba)->BooleanValue())
783
1
    uv_process_options_.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
784
785
1184
  Local<Value> js_timeout = js_options->Get(env()->timeout_string());
786
592
  if (IsSet(js_timeout)) {
787
7
    CHECK(js_timeout->IsNumber());
788
7
    int64_t timeout = js_timeout->IntegerValue();
789
7
    timeout_ = static_cast<uint64_t>(timeout);
790
  }
791
792
1184
  Local<Value> js_max_buffer = js_options->Get(env()->max_buffer_string());
793
592
  if (IsSet(js_max_buffer)) {
794
6
    CHECK(js_max_buffer->IsNumber());
795
6
    max_buffer_ = js_max_buffer->NumberValue();
796
  }
797
798
1184
  Local<Value> js_kill_signal = js_options->Get(env()->kill_signal_string());
799
592
  if (IsSet(js_kill_signal)) {
800
105
    CHECK(js_kill_signal->IsInt32());
801
105
    kill_signal_ = js_kill_signal->Int32Value();
802
  }
803
804
1184
  Local<Value> js_stdio = js_options->Get(env()->stdio_string());
805
592
  r = ParseStdioOptions(js_stdio);
806
592
  if (r < 0)
807
    return r;
808
809
592
  return 0;
810
}
811
812
813
592
int SyncProcessRunner::ParseStdioOptions(Local<Value> js_value) {
814
592
  HandleScope scope(env()->isolate());
815
  Local<Array> js_stdio_options;
816
817
592
  if (!js_value->IsArray())
818
    return UV_EINVAL;
819
820
592
  js_stdio_options = js_value.As<Array>();
821
822
592
  stdio_count_ = js_stdio_options->Length();
823
592
  uv_stdio_containers_ = new uv_stdio_container_t[stdio_count_];
824
825

592
  stdio_pipes_ = new SyncProcessStdioPipe*[stdio_count_]();
826
592
  stdio_pipes_initialized_ = true;
827
828
4736
  for (uint32_t i = 0; i < stdio_count_; i++) {
829
1776
    Local<Value> js_stdio_option = js_stdio_options->Get(i);
830
831
1776
    if (!js_stdio_option->IsObject())
832
      return UV_EINVAL;
833
834
1776
    int r = ParseStdioOption(i, js_stdio_option.As<Object>());
835
1776
    if (r < 0)
836
      return r;
837
  }
838
839
592
  uv_process_options_.stdio = uv_stdio_containers_;
840
592
  uv_process_options_.stdio_count = stdio_count_;
841
842
592
  return 0;
843
}
844
845
846
1776
int SyncProcessRunner::ParseStdioOption(int child_fd,
847
                                        Local<Object> js_stdio_option) {
848
3552
  Local<Value> js_type = js_stdio_option->Get(env()->type_string());
849
850
3552
  if (js_type->StrictEquals(env()->ignore_string())) {
851
6
    return AddStdioIgnore(child_fd);
852
853
3540
  } else if (js_type->StrictEquals(env()->pipe_string())) {
854
1764
    Local<String> rs = env()->readable_string();
855
1764
    Local<String> ws = env()->writable_string();
856
857
3528
    bool readable = js_stdio_option->Get(rs)->BooleanValue();
858
3528
    bool writable = js_stdio_option->Get(ws)->BooleanValue();
859
860
1764
    uv_buf_t buf = uv_buf_init(nullptr, 0);
861
862
1764
    if (readable) {
863
1176
      Local<Value> input = js_stdio_option->Get(env()->input_string());
864
588
      if (Buffer::HasInstance(input)) {
865
        buf = uv_buf_init(Buffer::Data(input),
866
7
                          static_cast<unsigned int>(Buffer::Length(input)));
867

1162
      } else if (!input->IsUndefined() && !input->IsNull()) {
868
        // Strings, numbers etc. are currently unsupported. It's not possible
869
        // to create a buffer for them here because there is no way to free
870
        // them afterwards.
871
        return UV_EINVAL;
872
      }
873
    }
874
875
1764
    return AddStdioPipe(child_fd, readable, writable, buf);
876
877


30
  } else if (js_type->StrictEquals(env()->inherit_string()) ||
878
12
             js_type->StrictEquals(env()->fd_string())) {
879
18
    int inherit_fd = js_stdio_option->Get(env()->fd_string())->Int32Value();
880
6
    return AddStdioInheritFD(child_fd, inherit_fd);
881
882
  } else {
883
    CHECK(0 && "invalid child stdio type");
884
    return UV_EINVAL;
885
  }
886
}
887
888
889
6
int SyncProcessRunner::AddStdioIgnore(uint32_t child_fd) {
890
6
  CHECK_LT(child_fd, stdio_count_);
891
6
  CHECK_EQ(stdio_pipes_[child_fd], nullptr);
892
893
6
  uv_stdio_containers_[child_fd].flags = UV_IGNORE;
894
895
6
  return 0;
896
}
897
898
899
1764
int SyncProcessRunner::AddStdioPipe(uint32_t child_fd,
900
                                    bool readable,
901
                                    bool writable,
902
                                    uv_buf_t input_buffer) {
903
1764
  CHECK_LT(child_fd, stdio_count_);
904
1764
  CHECK_EQ(stdio_pipes_[child_fd], nullptr);
905
906
  SyncProcessStdioPipe* h = new SyncProcessStdioPipe(this,
907
                                                     readable,
908
                                                     writable,
909
1764
                                                     input_buffer);
910
911
1764
  int r = h->Initialize(uv_loop_);
912
1764
  if (r < 0) {
913
    delete h;
914
    return r;
915
  }
916
917
1764
  stdio_pipes_[child_fd] = h;
918
919
1764
  uv_stdio_containers_[child_fd].flags = h->uv_flags();
920
1764
  uv_stdio_containers_[child_fd].data.stream = h->uv_stream();
921
922
1764
  return 0;
923
}
924
925
926
6
int SyncProcessRunner::AddStdioInheritFD(uint32_t child_fd, int inherit_fd) {
927
6
  CHECK_LT(child_fd, stdio_count_);
928
6
  CHECK_EQ(stdio_pipes_[child_fd], nullptr);
929
930
6
  uv_stdio_containers_[child_fd].flags = UV_INHERIT_FD;
931
6
  uv_stdio_containers_[child_fd].data.fd = inherit_fd;
932
933
6
  return 0;
934
}
935
936
937
4144
bool SyncProcessRunner::IsSet(Local<Value> value) {
938

9766
  return !value->IsUndefined() && !value->IsNull();
939
}
940
941
942
614
int SyncProcessRunner::CopyJsString(Local<Value> js_value,
943
                                    const char** target) {
944
614
  Isolate* isolate = env()->isolate();
945
  Local<String> js_string;
946
  size_t size, written;
947
  char* buffer;
948
949
1228
  if (js_value->IsString())
950
614
    js_string = js_value.As<String>();
951
  else
952
    js_string = js_value->ToString(env()->isolate());
953
954
  // Include space for null terminator byte.
955
614
  size = StringBytes::StorageSize(isolate, js_string, UTF8) + 1;
956
957
614
  buffer = new char[size];
958
959
614
  written = StringBytes::Write(isolate, buffer, -1, js_string, UTF8);
960
614
  buffer[written] = '\0';
961
962
614
  *target = buffer;
963
614
  return 0;
964
}
965
966
967
1184
int SyncProcessRunner::CopyJsStringArray(Local<Value> js_value,
968
                                         char** target) {
969
1184
  Isolate* isolate = env()->isolate();
970
  Local<Array> js_array;
971
  uint32_t length;
972
  size_t list_size, data_size, data_offset;
973
  char** list;
974
  char* buffer;
975
976
1184
  if (!js_value->IsArray())
977
    return UV_EINVAL;
978
979
3552
  js_array = js_value.As<Array>()->Clone().As<Array>();
980
1184
  length = js_array->Length();
981
982
  // Convert all array elements to string. Modify the js object itself if
983
  // needed - it's okay since we cloned the original object.
984
22957
  for (uint32_t i = 0; i < length; i++) {
985
65319
    if (!js_array->Get(i)->IsString())
986
8
      js_array->Set(i, js_array->Get(i)->ToString(env()->isolate()));
987
  }
988
989
  // Index has a pointer to every string element, plus one more for a final
990
  // null pointer.
991
1184
  list_size = (length + 1) * sizeof *list;
992
993
  // Compute the length of all strings. Include room for null terminator
994
  // after every string. Align strings to cache lines.
995
1184
  data_size = 0;
996
22957
  for (uint32_t i = 0; i < length; i++) {
997
21773
    data_size += StringBytes::StorageSize(isolate, js_array->Get(i), UTF8) + 1;
998
21773
    data_size = ROUND_UP(data_size, sizeof(void*));
999
  }
1000
1001
1184
  buffer = new char[list_size + data_size];
1002
1003
1184
  list = reinterpret_cast<char**>(buffer);
1004
1184
  data_offset = list_size;
1005
1006
22957
  for (uint32_t i = 0; i < length; i++) {
1007
21773
    list[i] = buffer + data_offset;
1008
    data_offset += StringBytes::Write(isolate,
1009
                                      buffer + data_offset,
1010
                                      -1,
1011
21773
                                      js_array->Get(i),
1012
21773
                                      UTF8);
1013
21773
    buffer[data_offset++] = '\0';
1014
21773
    data_offset = ROUND_UP(data_offset, sizeof(void*));
1015
  }
1016
1017
1184
  list[length] = nullptr;
1018
1019
1184
  *target = buffer;
1020
1184
  return 0;
1021
}
1022
1023
1024
182
void SyncProcessRunner::ExitCallback(uv_process_t* handle,
1025
                                     int64_t exit_status,
1026
                                     int term_signal) {
1027
182
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
1028
182
  uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
1029
182
  self->OnExit(exit_status, term_signal);
1030
182
}
1031
1032
1033
5
void SyncProcessRunner::KillTimerCallback(uv_timer_t* handle) {
1034
5
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
1035
5
  self->OnKillTimerTimeout();
1036
5
}
1037
1038
1039
6
void SyncProcessRunner::KillTimerCloseCallback(uv_handle_t* handle) {
1040
  // No-op.
1041
6
}
1042
1043
}  // namespace node
1044
1045
2441
NODE_MODULE_CONTEXT_AWARE_BUILTIN(spawn_sync,
1046
  node::SyncProcessRunner::Initialize)