Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/util/io/PopenExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import static org.jruby.api.Create.*;
import static org.jruby.api.Error.argumentError;
import static org.jruby.api.Error.runtimeError;
import static org.jruby.api.Error.typeError;
import static org.jruby.runtime.Helpers.arrayOf;

/**
Expand Down Expand Up @@ -128,6 +129,8 @@ public IRubyObject systemInternal(ThreadContext context, IRubyObject[] argv, Str
if (pid > 0) {
long ret;
ret = RubyProcess.waitpid(context, pid, 0);
// a blocking waitpid only returns 0 when the scheduler's process_wait returned nil
if (ret == 0) throw typeError(context, "wrong argument type nil (expected Process::Status)");
if (ret == -1)
throw runtime.newErrnoFromInt(runtime.getPosix().errno(), "Another thread waited the process started by system().");
}
Expand Down
27 changes: 27 additions & 0 deletions spec/ruby/core/kernel/system_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@
end
end

platform_is_not :windows do
describe "Kernel#system with Fiber scheduler" do
require_relative '../fiber/fixtures/scheduler'

before :each do
@scheduler = Class.new(FiberSpecs::LoggingScheduler) do
def process_wait(pid, flags)
Fiber.blocking { Process::Status.wait(pid, flags) }
nil
end
end.new
Fiber.set_scheduler(@scheduler)
end

after :each do
Fiber.set_scheduler(nil)
end

it "raises TypeError when the scheduler's process_wait does not return a Process::Status" do
waiter = Fiber.new(blocking: false) do
-> { system(ruby_cmd('exit 0')) }.should raise_error(TypeError, "wrong argument type nil (expected Process::Status)")
end
waiter.resume
end
end
end

describe "Kernel.system" do
it "is a public method" do
Kernel.public_methods(false).should.include?(:system)
Expand Down
Loading