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: 472 515 91.7 %
Date: 2017-11-19 Branches: 205 308 66.6 %

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
953
SyncProcessOutputBuffer::SyncProcessOutputBuffer()
49
    : used_(0),
50
953
      next_(nullptr) {
51
953
}
52
53
54
8734
void SyncProcessOutputBuffer::OnAlloc(size_t suggested_size,
55
                                      uv_buf_t* buf) const {
56
8734
  if (used() == kBufferSize)
57
    *buf = uv_buf_init(nullptr, 0);
58
  else
59
8734
    *buf = uv_buf_init(data_ + used(), available());
60
8734
}
61
62
63
7801
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
7801
  CHECK_EQ(buf->base, data_ + used());
66
7801
  used_ += static_cast<unsigned int>(nread);
67
7801
}
68
69
70
953
size_t SyncProcessOutputBuffer::Copy(char* dest) const {
71
953
  memcpy(dest, data_, used());
72
953
  return used();
73
}
74
75
76
16525
unsigned int SyncProcessOutputBuffer::available() const {
77
16525
  return sizeof data_ - used();
78
}
79
80
81
44653
unsigned int SyncProcessOutputBuffer::used() const {
82
44653
  return used_;
83
}
84
85
86
2859
SyncProcessOutputBuffer* SyncProcessOutputBuffer::next() const {
87
2859
  return next_;
88
}
89
90
91
10
void SyncProcessOutputBuffer::set_next(SyncProcessOutputBuffer* next) {
92
10
  next_ = next;
93
10
}
94
95
96
3786
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
3786
      lifecycle_(kUninitialized) {
113

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

3786
  CHECK(lifecycle_ == kUninitialized || lifecycle_ == kClosed);
119
120
  SyncProcessOutputBuffer* buf;
121
  SyncProcessOutputBuffer* next;
122
123
4739
  for (buf = first_output_buffer_; buf != nullptr; buf = next) {
124
953
    next = buf->next();
125
953
    delete buf;
126
  }
127
3786
}
128
129
130
3786
int SyncProcessStdioPipe::Initialize(uv_loop_t* loop) {
131
3786
  CHECK_EQ(lifecycle_, kUninitialized);
132
133
3786
  int r = uv_pipe_init(loop, uv_pipe(), 0);
134
3786
  if (r < 0)
135
    return r;
136
137
3786
  uv_pipe()->data = this;
138
139
3786
  lifecycle_ = kInitialized;
140
3786
  return 0;
141
}
142
143
144
1431
int SyncProcessStdioPipe::Start() {
145
1431
  CHECK_EQ(lifecycle_, kInitialized);
146
147
  // Set the busy flag already. If this function fails no recovery is
148
  // possible.
149
1431
  lifecycle_ = kStarted;
150
151
1431
  if (readable()) {
152
477
    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
477
    int r = uv_shutdown(&shutdown_req_, uv_stream(), ShutdownCallback);
165
477
    if (r < 0)
166
      return r;
167
  }
168
169
1431
  if (writable()) {
170
954
    int r = uv_read_start(uv_stream(), AllocCallback, ReadCallback);
171
954
    if (r < 0)
172
      return r;
173
  }
174
175
1431
  return 0;
176
}
177
178
179
3786
void SyncProcessStdioPipe::Close() {
180

3786
  CHECK(lifecycle_ == kInitialized || lifecycle_ == kStarted);
181
182
3786
  uv_close(uv_handle(), CloseCallback);
183
184
3786
  lifecycle_ = kClosing;
185
3786
}
186
187
188
954
Local<Object> SyncProcessStdioPipe::GetOutputAsBuffer(Environment* env) const {
189
954
  size_t length = OutputLength();
190
1908
  Local<Object> js_buffer = Buffer::New(env, length).ToLocalChecked();
191
954
  CopyOutput(Buffer::Data(js_buffer));
192
954
  return js_buffer;
193
}
194
195
196
5217
bool SyncProcessStdioPipe::readable() const {
197
5217
  return readable_;
198
}
199
200
201
6648
bool SyncProcessStdioPipe::writable() const {
202
6648
  return writable_;
203
}
204
205
206
3786
uv_stdio_flags SyncProcessStdioPipe::uv_flags() const {
207
  unsigned int flags;
208
209
3786
  flags = UV_CREATE_PIPE;
210
3786
  if (readable())
211
1262
    flags |= UV_READABLE_PIPE;
212
3786
  if (writable())
213
2524
    flags |= UV_WRITABLE_PIPE;
214
215
3786
  return static_cast<uv_stdio_flags>(flags);
216
}
217
218
219
16582
uv_pipe_t* SyncProcessStdioPipe::uv_pipe() const {
220
16582
  CHECK_LT(lifecycle_, kClosing);
221
16582
  return &uv_pipe_;
222
}
223
224
225
5224
uv_stream_t* SyncProcessStdioPipe::uv_stream() const {
226
5224
  return reinterpret_cast<uv_stream_t*>(uv_pipe());
227
}
228
229
230
3786
uv_handle_t* SyncProcessStdioPipe::uv_handle() const {
231
3786
  return reinterpret_cast<uv_handle_t*>(uv_pipe());
232
}
233
234
235
954
size_t SyncProcessStdioPipe::OutputLength() const {
236
  SyncProcessOutputBuffer* buf;
237
954
  size_t size = 0;
238
239
1907
  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
240
953
    size += buf->used();
241
242
954
  return size;
243
}
244
245
246
954
void SyncProcessStdioPipe::CopyOutput(char* dest) const {
247
  SyncProcessOutputBuffer* buf;
248
954
  size_t offset = 0;
249
250
1907
  for (buf = first_output_buffer_; buf != nullptr; buf = buf->next())
251
953
    offset += buf->Copy(dest + offset);
252
954
}
253
254
255
8734
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
8734
  if (last_output_buffer_ == nullptr) {
262
    // Allocate the first capture buffer.
263
943
    first_output_buffer_ = new SyncProcessOutputBuffer();
264
943
    last_output_buffer_ = first_output_buffer_;
265
266
7791
  } else if (last_output_buffer_->available() == 0) {
267
    // The current capture buffer is full so get us a new one.
268
10
    SyncProcessOutputBuffer* buf = new SyncProcessOutputBuffer();
269
10
    last_output_buffer_->set_next(buf);
270
10
    last_output_buffer_ = buf;
271
  }
272
273
8734
  last_output_buffer_->OnAlloc(suggested_size, buf);
274
8734
}
275
276
277
8743
void SyncProcessStdioPipe::OnRead(const uv_buf_t* buf, ssize_t nread) {
278
8743
  if (nread == UV_EOF) {
279
    // Libuv implicitly stops reading on EOF.
280
281
7801
  } 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
7801
    last_output_buffer_->OnRead(buf, nread);
288
7801
    process_handler_->IncrementBufferSizeAndCheckOverflow(nread);
289
  }
290
8743
}
291
292
293
7
void SyncProcessStdioPipe::OnWriteDone(int result) {
294
7
  if (result < 0)
295
    SetError(result);
296
7
}
297
298
299
477
void SyncProcessStdioPipe::OnShutdownDone(int result) {
300
477
  if (result < 0)
301
    SetError(result);
302
477
}
303
304
305
3786
void SyncProcessStdioPipe::OnClose() {
306
3786
  lifecycle_ = kClosed;
307
3786
}
308
309
310
void SyncProcessStdioPipe::SetError(int error) {
311
  CHECK_NE(error, 0);
312
  process_handler_->SetPipeError(error);
313
}
314
315
316
8734
void SyncProcessStdioPipe::AllocCallback(uv_handle_t* handle,
317
                                         size_t suggested_size,
318
                                         uv_buf_t* buf) {
319
  SyncProcessStdioPipe* self =
320
8734
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
321
8734
  self->OnAlloc(suggested_size, buf);
322
8734
}
323
324
325
8743
void SyncProcessStdioPipe::ReadCallback(uv_stream_t* stream,
326
                                        ssize_t nread,
327
                                        const uv_buf_t* buf) {
328
  SyncProcessStdioPipe* self =
329
8743
        reinterpret_cast<SyncProcessStdioPipe*>(stream->data);
330
8743
  self->OnRead(buf, nread);
331
8743
}
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
477
void SyncProcessStdioPipe::ShutdownCallback(uv_shutdown_t* req, int result) {
342
  SyncProcessStdioPipe* self =
343
477
      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
477
  if (result == UV_ENOTCONN)
350
    result = 0;
351
352
477
  self->OnShutdownDone(result);
353
477
}
354
355
356
3786
void SyncProcessStdioPipe::CloseCallback(uv_handle_t* handle) {
357
  SyncProcessStdioPipe* self =
358
3786
      reinterpret_cast<SyncProcessStdioPipe*>(handle->data);
359
3786
  self->OnClose();
360
3786
}
361
362
363
2898
void SyncProcessRunner::Initialize(Local<Object> target,
364
                                   Local<Value> unused,
365
                                   Local<Context> context) {
366
2898
  Environment* env = Environment::GetCurrent(context);
367
2898
  env->SetMethod(target, "spawn", Spawn);
368
2898
}
369
370
371
1266
void SyncProcessRunner::Spawn(const FunctionCallbackInfo<Value>& args) {
372
1266
  Environment* env = Environment::GetCurrent(args);
373
1266
  env->PrintSyncTrace();
374
1266
  SyncProcessRunner p(env);
375
1266
  Local<Value> result = p.Run(args[0]);
376
2532
  args.GetReturnValue().Set(result);
377
1266
}
378
379
380
1266
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
1266
      env_(env) {
414
1266
}
415
416
417
2532
SyncProcessRunner::~SyncProcessRunner() {
418
1266
  CHECK_EQ(lifecycle_, kHandlesClosed);
419
420
1266
  stdio_pipes_.reset();
421
1266
  delete[] file_buffer_;
422
1266
  delete[] args_buffer_;
423
1266
  delete[] cwd_buffer_;
424
1266
  delete[] env_buffer_;
425
1266
  delete[] uv_stdio_containers_;
426
1266
}
427
428
429
71091
Environment* SyncProcessRunner::env() const {
430
71091
  return env_;
431
}
432
433
434
1266
Local<Object> SyncProcessRunner::Run(Local<Value> options) {
435
1266
  EscapableHandleScope scope(env()->isolate());
436
437
1266
  CHECK_EQ(lifecycle_, kUninitialized);
438
439
1266
  TryInitializeAndRunLoop(options);
440
1266
  CloseHandlesAndDeleteLoop();
441
442
1266
  Local<Object> result = BuildResultObject();
443
444
1266
  return scope.Escape(result);
445
}
446
447
448
1266
void SyncProcessRunner::TryInitializeAndRunLoop(Local<Value> options) {
449
  int r;
450
451
  // There is no recovery from failure inside TryInitializeAndRunLoop - the
452
  // only option we'd have is to close all handles and destroy the loop.
453
1266
  CHECK_EQ(lifecycle_, kUninitialized);
454
1266
  lifecycle_ = kInitialized;
455
456
1266
  uv_loop_ = new uv_loop_t;
457
1266
  if (uv_loop_ == nullptr)
458
    return SetError(UV_ENOMEM);
459
1266
  CHECK_EQ(uv_loop_init(uv_loop_), 0);
460
461
1266
  r = ParseOptions(options);
462
1266
  if (r < 0)
463
    return SetError(r);
464
465
1266
  if (timeout_ > 0) {
466
6
    r = uv_timer_init(uv_loop_, &uv_timer_);
467
6
    if (r < 0)
468
      return SetError(r);
469
470
6
    uv_unref(reinterpret_cast<uv_handle_t*>(&uv_timer_));
471
472
6
    uv_timer_.data = this;
473
6
    kill_timer_initialized_ = true;
474
475
    // Start the timer immediately. If uv_spawn fails then
476
    // CloseHandlesAndDeleteLoop() will immediately close the timer handle
477
    // which implicitly stops it, so there is no risk that the timeout callback
478
    // runs when the process didn't start.
479
6
    r = uv_timer_start(&uv_timer_, KillTimerCallback, timeout_, 0);
480
6
    if (r < 0)
481
      return SetError(r);
482
  }
483
484
1266
  uv_process_options_.exit_cb = ExitCallback;
485
1266
  r = uv_spawn(uv_loop_, &uv_process_, &uv_process_options_);
486
1266
  if (r < 0)
487
785
    return SetError(r);
488
481
  uv_process_.data = this;
489
490
1924
  for (uint32_t i = 0; i < stdio_count_; i++) {
491
1443
    SyncProcessStdioPipe* h = stdio_pipes_[i].get();
492
1443
    if (h != nullptr) {
493
1431
      r = h->Start();
494
1431
      if (r < 0)
495
        return SetPipeError(r);
496
    }
497
  }
498
499
481
  r = uv_run(uv_loop_, UV_RUN_DEFAULT);
500
481
  if (r < 0)
501
    // We can't handle uv_run failure.
502
    ABORT();
503
504
  // If we get here the process should have exited.
505
481
  CHECK_GE(exit_status_, 0);
506
}
507
508
509
1266
void SyncProcessRunner::CloseHandlesAndDeleteLoop() {
510
1266
  CHECK_LT(lifecycle_, kHandlesClosed);
511
512
1266
  if (uv_loop_ != nullptr) {
513
1266
    CloseStdioPipes();
514
1266
    CloseKillTimer();
515
    // Close the process handle when ExitCallback was not called.
516
    uv_handle_t* uv_process_handle =
517
1266
        reinterpret_cast<uv_handle_t*>(&uv_process_);
518
519
    // Close the process handle if it is still open. The handle type also
520
    // needs to be checked because TryInitializeAndRunLoop() won't spawn a
521
    // process if input validation fails.
522

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

6
    if (r < 0 && r != UV_ESRCH) {
597
      SetError(r);
598
599
      r = uv_process_kill(&uv_process_, SIGKILL);
600
      CHECK(r >= 0 || r == UV_ESRCH);
601
    }
602
  }
603
604
  // Close all stdio pipes.
605
6
  CloseStdioPipes();
606
607
  // Stop the timeout timer immediately.
608
6
  CloseKillTimer();
609
}
610
611
612
7801
void SyncProcessRunner::IncrementBufferSizeAndCheckOverflow(ssize_t length) {
613
7801
  buffered_output_size_ += length;
614
615

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

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

1266
      new std::unique_ptr<SyncProcessStdioPipe>[stdio_count_]());
849
1266
  stdio_pipes_initialized_ = true;
850
851
10128
  for (uint32_t i = 0; i < stdio_count_; i++) {
852
    Local<Value> js_stdio_option =
853
7596
        js_stdio_options->Get(context, i).ToLocalChecked();
854
855
3798
    if (!js_stdio_option->IsObject())
856
      return UV_EINVAL;
857
858
3798
    int r = ParseStdioOption(i, js_stdio_option.As<Object>());
859
3798
    if (r < 0)
860
      return r;
861
  }
862
863
1266
  uv_process_options_.stdio = uv_stdio_containers_;
864
1266
  uv_process_options_.stdio_count = stdio_count_;
865
866
1266
  return 0;
867
}
868
869
870
3798
int SyncProcessRunner::ParseStdioOption(int child_fd,
871
                                        Local<Object> js_stdio_option) {
872
3798
  Local<Context> context = env()->context();
873
  Local<Value> js_type =
874
11394
      js_stdio_option->Get(context, env()->type_string()).ToLocalChecked();
875
876
7596
  if (js_type->StrictEquals(env()->ignore_string())) {
877
6
    return AddStdioIgnore(child_fd);
878
879
7584
  } else if (js_type->StrictEquals(env()->pipe_string())) {
880
3786
    Local<String> rs = env()->readable_string();
881
3786
    Local<String> ws = env()->writable_string();
882
883
7572
    bool readable = js_stdio_option->Get(context, rs)
884
15144
        .ToLocalChecked()->BooleanValue(context).FromJust();
885
    bool writable =
886
7572
        js_stdio_option->Get(context, ws)
887
15144
        .ToLocalChecked()->BooleanValue(context).FromJust();
888
889
3786
    uv_buf_t buf = uv_buf_init(nullptr, 0);
890
891
3786
    if (readable) {
892
      Local<Value> input =
893
3786
          js_stdio_option->Get(context, env()->input_string()).ToLocalChecked();
894
1262
      if (Buffer::HasInstance(input)) {
895
        buf = uv_buf_init(Buffer::Data(input),
896
7
                          static_cast<unsigned int>(Buffer::Length(input)));
897

2510
      } else if (!input->IsUndefined() && !input->IsNull()) {
898
        // Strings, numbers etc. are currently unsupported. It's not possible
899
        // to create a buffer for them here because there is no way to free
900
        // them afterwards.
901
        return UV_EINVAL;
902
      }
903
    }
904
905
3786
    return AddStdioPipe(child_fd, readable, writable, buf);
906
907


30
  } else if (js_type->StrictEquals(env()->inherit_string()) ||
908
12
             js_type->StrictEquals(env()->fd_string())) {
909
18
    int inherit_fd = js_stdio_option->Get(context, env()->fd_string())
910
24
        .ToLocalChecked()->Int32Value(context).FromJust();
911
6
    return AddStdioInheritFD(child_fd, inherit_fd);
912
913
  } else {
914
    CHECK(0 && "invalid child stdio type");
915
    return UV_EINVAL;
916
  }
917
}
918
919
920
6
int SyncProcessRunner::AddStdioIgnore(uint32_t child_fd) {
921
6
  CHECK_LT(child_fd, stdio_count_);
922
6
  CHECK(!stdio_pipes_[child_fd]);
923
924
6
  uv_stdio_containers_[child_fd].flags = UV_IGNORE;
925
926
6
  return 0;
927
}
928
929
930
3786
int SyncProcessRunner::AddStdioPipe(uint32_t child_fd,
931
                                    bool readable,
932
                                    bool writable,
933
                                    uv_buf_t input_buffer) {
934
3786
  CHECK_LT(child_fd, stdio_count_);
935
3786
  CHECK(!stdio_pipes_[child_fd]);
936
937
  std::unique_ptr<SyncProcessStdioPipe> h(
938
3786
      new SyncProcessStdioPipe(this, readable, writable, input_buffer));
939
940
3786
  int r = h->Initialize(uv_loop_);
941
3786
  if (r < 0) {
942
    h.reset();
943
    return r;
944
  }
945
946
3786
  uv_stdio_containers_[child_fd].flags = h->uv_flags();
947
3786
  uv_stdio_containers_[child_fd].data.stream = h->uv_stream();
948
949
3786
  stdio_pipes_[child_fd] = std::move(h);
950
951
3786
  return 0;
952
}
953
954
955
6
int SyncProcessRunner::AddStdioInheritFD(uint32_t child_fd, int inherit_fd) {
956
6
  CHECK_LT(child_fd, stdio_count_);
957
6
  CHECK(!stdio_pipes_[child_fd]);
958
959
6
  uv_stdio_containers_[child_fd].flags = UV_INHERIT_FD;
960
6
  uv_stdio_containers_[child_fd].data.fd = inherit_fd;
961
962
6
  return 0;
963
}
964
965
966
8862
bool SyncProcessRunner::IsSet(Local<Value> value) {
967

20552
  return !value->IsUndefined() && !value->IsNull();
968
}
969
970
971
1289
int SyncProcessRunner::CopyJsString(Local<Value> js_value,
972
                                    const char** target) {
973
1289
  Isolate* isolate = env()->isolate();
974
  Local<String> js_string;
975
  size_t size, written;
976
  char* buffer;
977
978
2578
  if (js_value->IsString())
979
1289
    js_string = js_value.As<String>();
980
  else
981
    js_string = js_value->ToString(env()->isolate());
982
983
  // Include space for null terminator byte.
984
1289
  size = StringBytes::StorageSize(isolate, js_string, UTF8) + 1;
985
986
1289
  buffer = new char[size];
987
988
1289
  written = StringBytes::Write(isolate, buffer, -1, js_string, UTF8);
989
1289
  buffer[written] = '\0';
990
991
1289
  *target = buffer;
992
1289
  return 0;
993
}
994
995
996
2532
int SyncProcessRunner::CopyJsStringArray(Local<Value> js_value,
997
                                         char** target) {
998
2532
  Isolate* isolate = env()->isolate();
999
  Local<Array> js_array;
1000
  uint32_t length;
1001
  size_t list_size, data_size, data_offset;
1002
  char** list;
1003
  char* buffer;
1004
1005
2532
  if (!js_value->IsArray())
1006
    return UV_EINVAL;
1007
1008
2532
  Local<Context> context = env()->context();
1009
7596
  js_array = js_value.As<Array>()->Clone().As<Array>();
1010
2532
  length = js_array->Length();
1011
2532
  data_size = 0;
1012
1013
  // Index has a pointer to every string element, plus one more for a final
1014
  // null pointer.
1015
2532
  list_size = (length + 1) * sizeof *list;
1016
1017
  // Convert all array elements to string. Modify the js object itself if
1018
  // needed - it's okay since we cloned the original object. Also compute the
1019
  // length of all strings, including room for a null terminator after every
1020
  // string. Align strings to cache lines.
1021
82128
  for (uint32_t i = 0; i < length; i++) {
1022
159192
    auto value = js_array->Get(context, i).ToLocalChecked();
1023
1024
159192
    if (!value->IsString())
1025
8
      js_array->Set(context, i, value->ToString(env()->isolate())).FromJust();
1026
1027
79596
    data_size += StringBytes::StorageSize(isolate, value, UTF8) + 1;
1028
79596
    data_size = ROUND_UP(data_size, sizeof(void*));
1029
  }
1030
1031
2532
  buffer = new char[list_size + data_size];
1032
1033
2532
  list = reinterpret_cast<char**>(buffer);
1034
2532
  data_offset = list_size;
1035
1036
82128
  for (uint32_t i = 0; i < length; i++) {
1037
79596
    list[i] = buffer + data_offset;
1038
159192
    auto value = js_array->Get(context, i).ToLocalChecked();
1039
    data_offset += StringBytes::Write(isolate,
1040
                                      buffer + data_offset,
1041
                                      -1,
1042
                                      value,
1043
79596
                                      UTF8);
1044
79596
    buffer[data_offset++] = '\0';
1045
79596
    data_offset = ROUND_UP(data_offset, sizeof(void*));
1046
  }
1047
1048
2532
  list[length] = nullptr;
1049
1050
2532
  *target = buffer;
1051
2532
  return 0;
1052
}
1053
1054
1055
481
void SyncProcessRunner::ExitCallback(uv_process_t* handle,
1056
                                     int64_t exit_status,
1057
                                     int term_signal) {
1058
481
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
1059
481
  uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
1060
481
  self->OnExit(exit_status, term_signal);
1061
481
}
1062
1063
1064
5
void SyncProcessRunner::KillTimerCallback(uv_timer_t* handle) {
1065
5
  SyncProcessRunner* self = reinterpret_cast<SyncProcessRunner*>(handle->data);
1066
5
  self->OnKillTimerTimeout();
1067
5
}
1068
1069
1070
6
void SyncProcessRunner::KillTimerCloseCallback(uv_handle_t* handle) {
1071
  // No-op.
1072
6
}
1073
1074
}  // namespace node
1075
1076
3332
NODE_BUILTIN_MODULE_CONTEXT_AWARE(spawn_sync,
1077
  node::SyncProcessRunner::Initialize)