Skip to content

Commit

Permalink
Don't block during spawn or backtick.
Browse files Browse the repository at this point in the history
  • Loading branch information
brixen committed Jun 9, 2016
1 parent ea90f6f commit ec8d11c
Showing 1 changed file with 96 additions and 84 deletions.
180 changes: 96 additions & 84 deletions machine/builtin/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,45 +482,48 @@ namespace rubinius {
exit(1);
}

close(errors[1]);

if(state->shared().config.system_log_lifetime.value) {
if(CallFrame* call_frame = state->vm()->get_noncore_frame(state)) {
logger::write("process: spawn: %d: %s, %s, %s:%d",
pid, exe.command(),
state->vm()->name().c_str(),
call_frame->file(state)->cpp_str(state).c_str(),
call_frame->line(state));
} else {
logger::write("process: spawn: %d: %s, %s",
pid, exe.command(),
state->vm()->name().c_str());
}
}

int error_no = 0;
ssize_t size;

while((size = read(errors[0], &error_no, sizeof(int))) < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
continue;
default:
logger::error("%s: spawn: reading error status", strerror(errno));
break;
{
UnmanagedPhase unmanaged(state);

close(errors[1]);

if(state->shared().config.system_log_lifetime.value) {
if(CallFrame* call_frame = state->vm()->get_noncore_frame(state)) {
logger::write("process: spawn: %d: %s, %s, %s:%d",
pid, exe.command(),
state->vm()->name().c_str(),
call_frame->file(state)->cpp_str(state).c_str(),
call_frame->line(state));
} else {
logger::write("process: spawn: %d: %s, %s",
pid, exe.command(),
state->vm()->name().c_str());
}
}
}
close(errors[0]);

if(size != 0) {
{
UnmanagedPhase unmanaged(state);
while((size = read(errors[0], &error_no, sizeof(int))) < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
continue;
default:
logger::error("%s: spawn: reading error status", strerror(errno));
break;
}
}
close(errors[0]);

if(size != 0) {
int status, options = 0;

waitpid(pid, &status, options);
}
}

if(size != 0) {
Exception::raise_errno_error(state, "execvp(2) failed", error_no);
return NULL;
}
Expand Down Expand Up @@ -603,83 +606,92 @@ namespace rubinius {
exit(1);
}

close(errors[1]);
close(output[1]);

if(state->shared().config.system_log_lifetime.value) {
if(CallFrame* call_frame = state->vm()->get_noncore_frame(state)) {
logger::write("process: backtick: %d: %s, %s, %s:%d",
pid, exe.command(),
state->vm()->name().c_str(),
call_frame->file(state)->cpp_str(state).c_str(),
call_frame->line(state));
} else {
logger::write("process: backtick: %d: %s, %s",
pid, exe.command(),
state->vm()->name().c_str());
}
}

int error_no = 0;
ssize_t size;

while((size = read(errors[0], &error_no, sizeof(int))) < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
continue;
default:
logger::error("%s: backtick: reading error status", strerror(errno));
break;
{
UnmanagedPhase unmanaged(state);

close(errors[1]);
close(output[1]);

if(state->shared().config.system_log_lifetime.value) {
if(CallFrame* call_frame = state->vm()->get_noncore_frame(state)) {
logger::write("process: backtick: %d: %s, %s, %s:%d",
pid, exe.command(),
state->vm()->name().c_str(),
call_frame->file(state)->cpp_str(state).c_str(),
call_frame->line(state));
} else {
logger::write("process: backtick: %d: %s, %s",
pid, exe.command(),
state->vm()->name().c_str());
}
}
}
close(errors[0]);

if(size != 0) {
{
UnmanagedPhase unmanaged(state);
while((size = read(errors[0], &error_no, sizeof(int))) < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
continue;
default:
logger::error("%s: backtick: reading error status", strerror(errno));
break;
}
}
close(errors[0]);

if(size != 0) {
int status, options = 0;

waitpid(pid, &status, options);
close(output[0]);
}
}

close(output[0]);
if(size != 0) {
Exception::raise_errno_error(state, "execvp(2) failed", error_no);
return NULL;
}

std::string buf;
for(;;) {

ssize_t bytes = 0;
char raw_buf[1024];
{
UnmanagedPhase unmanaged(state);
bytes = read(output[0], raw_buf, 1023);
}
{
UnmanagedPhase unmanaged(state);

if(bytes < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
if(state->vm()->thread_interrupted_p(state)) {
for(;;) {
char raw_buf[1024];
ssize_t bytes = read(output[0], raw_buf, 1023);

if(bytes < 0) {
switch(errno) {
case EAGAIN:
case EINTR:
{
ManagedPhase managed(state);
if(state->vm()->thread_interrupted_p(state)) {
close(output[0]);
return NULL;
}
}
continue;
default:
close(output[0]);
return NULL;
}
continue;
default:
close(output[0]);
Exception::raise_errno_error(state, "reading child data", errno, "read(2)");
{
ManagedPhase managed(state);
Exception::raise_errno_error(state, "reading child data", errno, "read(2)");
}
}
}
}

if(bytes == 0) {
break;
if(bytes == 0) {
break;
}
buf.append(raw_buf, bytes);
}
buf.append(raw_buf, bytes);
}

close(output[0]);
close(output[0]);
}

return Tuple::from(state, 2, Fixnum::from(pid),
String::create(state, buf.c_str(), buf.size()));
Expand Down

0 comments on commit ec8d11c

Please sign in to comment.