#include "spawn_sync.h"
#include "env-inl.h"
#include "string_bytes.h"
#include "util.h"
#include
#include
namespace node {
using v8::Array;
using v8::Context;
using v8::EscapableHandleScope;
using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::Integer;
using v8::Isolate;
using v8::Local;
using v8::Null;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
SyncProcessOutputBuffer::SyncProcessOutputBuffer()
: used_(0),
next_(nullptr) {
}
void SyncProcessOutputBuffer::OnAlloc(size_t suggested_size,
uv_buf_t* buf) const {
if (used() == kBufferSize)
*buf = uv_buf_init(nullptr, 0);
else
*buf = uv_buf_init(data_ + used(), available());
}
void SyncProcessOutputBuffer::OnRead(const uv_buf_t* buf, size_t nread) {
// If we hand out the same chunk twice, this should catch it.
CHECK_EQ(buf->base, data_ + used());
used_ += static_cast(nread);
}
size_t SyncProcessOutputBuffer::Copy(char* dest) const {
memcpy(dest, data_, used());
return used();
}
unsigned int SyncProcessOutputBuffer::available() const {
return sizeof data_ - used();
}
unsigned int SyncProcessOutputBuffer::used() const {
return used_;
}
SyncProcessOutputBuffer* SyncProcessOutputBuffer::next() const {
return next_;
}
void SyncProcessOutputBuffer::set_next(SyncProcessOutputBuffer* next) {
next_ = next;
}
SyncProcessStdioPipe::SyncProcessStdioPipe(SyncProcessRunner* process_handler,
bool readable,
bool writable,
uv_buf_t input_buffer)
: process_handler_(process_handler),
readable_(readable),
writable_(writable),
input_buffer_(input_buffer),
first_output_buffer_(nullptr),
last_output_buffer_(nullptr),
uv_pipe_(),
write_req_(),
shutdown_req_(),
lifecycle_(kUninitialized) {
CHECK(readable || writable);
}
SyncProcessStdioPipe::~SyncProcessStdioPipe() {
CHECK(lifecycle_ == kUninitialized || lifecycle_ == kClosed);
SyncProcessOutputBuffer* buf;
SyncProcessOutputBuffer* next;
for (buf = first_output_buffer_; buf != nullptr; buf = next) {
next = buf->next();
delete buf;
}
}
int SyncProcessStdioPipe::Initialize(uv_loop_t* loop) {
CHECK_EQ(lifecycle_, kUninitialized);
int r = uv_pipe_init(loop, uv_pipe(), 0);
if (r < 0)
return r;
uv_pipe()->data = this;
lifecycle_ = kInitialized;
return 0;
}
int SyncProcessStdioPipe::Start() {
CHECK_EQ(lifecycle_, kInitialized);
// Set the busy flag already. If this function fails no recovery is
// possible.
lifecycle_ = kStarted;
if (readable()) {
if (input_buffer_.len > 0) {
CHECK_NE(input_buffer_.base, nullptr);
int r = uv_write(&write_req_,
uv_stream(),
&input_buffer_,
1,
WriteCallback);
if (r < 0)
return r;
}
int r = uv_shutdown(&shutdown_req_, uv_stream(), ShutdownCallback);
if (r < 0)
return r;
}
if (writable()) {
int r = uv_read_start(uv_stream(), AllocCallback, ReadCallback);
if (r < 0)
return r;
}
return 0;
}
void SyncProcessStdioPipe::Close() {
CHECK(lifecycle_ == kInitialized || lifecycle_ == kStarted);
uv_close(uv_handle(), CloseCallback);
lifecycle_ = kClosing;
}
Local