Permalink
Browse files

Merge branch 'master' of git://github.com/rubinius/rubinius

  • Loading branch information...
2 parents d97677d + 9153ef6 commit 03248a938f9cc188d9ed24b0762498087bd6e680 @ryoqun committed May 9, 2012
View
@@ -24,7 +24,6 @@ def initialize
@internal[:$"] = loaded_features
@internal[:$,] = nil # Output field separator
@internal[:$.] = 0
- @internal[:$?] = nil # Process status. nil until set
@internal[:$=] = false # ignore case, whatever that is
@internal[:$0] = nil
@internal[:$CONSOLE] = STDOUT
@@ -114,6 +114,10 @@ def autoload(name, path)
def constants(all=undefined)
tbl = Rubinius::LookupTable.new
+ # When calling `constants` on "normal" classes the result does not include
+ # their own class name. BasicObject is a special case in this regard.
+ tbl[:BasicObject] = true if self == BasicObject
+
@constant_table.each do |name, val|
tbl[name] = true
end
View
@@ -337,7 +337,7 @@ def self.wait2(input_pid=-1, flags=nil)
status, termsig, stopsig, pid = value
status = Process::Status.new(pid, status, termsig, stopsig)
- Rubinius::Globals.set! :$?, status
+ set_status_global status
[pid, status]
end
@@ -376,27 +376,6 @@ class << self
alias_method :waitpid2, :wait2
end
- #
- # Indicate disinterest in child process.
- #
- # Sets up an internal wait on the given process ID.
- # Only possibly real pids, i.e. positive numbers,
- # may be waited for.
- #
- # TODO: Should an error be raised on ECHILD? --rue
- #
- # TODO: This operates on the assumption that waiting on
- # the event consumes very little resources. If this
- # is not the case, the check should be made WNOHANG
- # and called periodically.
- #
- def self.detach(pid)
- raise ArgumentError, "Only positive pids may be detached" unless pid > 0
-
- # The evented system does not need a loop
- Thread.new { Process.wait pid }
- end
-
#--
# TODO: Most of the fields aren't implemented yet.
# TODO: Also, these objects should only need to be constructed by
View
@@ -1,4 +1,10 @@
module Process
+ Rubinius::Globals.read_only :$?
+
+ def self.set_status_global(status)
+ Rubinius::Globals.set! :$?, status
+ end
+
def self.exec(cmd, *args)
if args.empty? and cmd.kind_of? String
raise Errno::ENOENT if cmd.empty?
@@ -25,6 +31,20 @@ def self.exec(cmd, *args)
Process.perform_exec prog, argv
end
end
+
+ # TODO: Should an error be raised on ECHILD? --rue
+ #
+ # TODO: This operates on the assumption that waiting on
+ # the event consumes very little resources. If this
+ # is not the case, the check should be made WNOHANG
+ # and called periodically.
+ #
+ def self.detach(pid)
+ raise ArgumentError, "Only positive pids may be detached" unless pid > 0
+
+ # The evented system does not need a loop
+ Thread.new { Process.wait pid; $? }
+ end
end
module Kernel
View
@@ -242,6 +242,13 @@ def self.exec(env, prog, argv, redirects, options)
end
module Process
+ Rubinius::Globals.read_only :$?
+ Rubinius::Globals.set_hook(:$?) { Thread.current[:$?] }
+
+ def self.set_status_global(status)
+ Thread.current[:$?] = status
+ end
+
def self.daemon(stay_in_dir=false, keep_stdio_open=false)
# Do not run at_exit handlers in the parent
exit!(0) if fork
@@ -289,6 +296,23 @@ def self.spawn(*args)
pid
end
end
+
+ # TODO: Should an error be raised on ECHILD? --rue
+ #
+ # TODO: This operates on the assumption that waiting on
+ # the event consumes very little resources. If this
+ # is not the case, the check should be made WNOHANG
+ # and called periodically.
+ #
+ def self.detach(pid)
+ raise ArgumentError, "Only positive pids may be detached" unless pid > 0
+
+ thread = Thread.new { Process.wait pid; $? }
+ thread[:pid] = pid
+ def thread.pid; self[:pid] end
+
+ thread
+ end
end
module Kernel
View
@@ -136,7 +136,6 @@ def method_missing(meth, *args)
Rubinius::Globals.read_only :$:, :$LOAD_PATH, :$-I
Rubinius::Globals.read_only :$", :$LOADED_FEATURES
Rubinius::Globals.read_only :$<
- Rubinius::Globals.read_only :$?
Rubinius::Globals[:$-a] = false
Rubinius::Globals[:$-l] = false
View
@@ -199,6 +199,7 @@ def popen2e(*cmd, &block)
module_function :popen2e
def popen_run(cmd, opts, child_io, parent_io) # :nodoc:
+ parent_io.each {|io| io.close_on_exec = true }
pid = spawn(*cmd, opts)
wait_thr = Process.detach(pid)
child_io.each {|io| io.close }
@@ -99,15 +99,15 @@ def unmarshal(stream)
def unmarshal_data
kind = next_type
case kind
- when ?t
+ when 116 # ?t
return true
- when ?f
+ when 102 # ?f
return false
- when ?n
+ when 110 # ?n
return nil
- when ?I
+ when 73 # ?I
return next_string.to_i(16)
- when ?d
+ when 100 # ?d
str = next_string.chop
# handle the special NaN, Infinity and -Infinity differently
@@ -133,24 +133,21 @@ def unmarshal_data
raise TypeError, "Invalid Float format: #{str}"
end
end
- when ?s
+ when 115 # ?s
enc = unmarshal_data
count = next_string.to_i
str = next_bytes count
str.force_encoding enc if enc and defined?(Encoding)
- discard # remove the \n
return str
- when ?x
+ when 120 # ?x
count = next_string.to_i
str = next_bytes count
- discard # remove the \n
return str.to_sym
- when ?c
+ when 99 # ?c
count = next_string.to_i
str = next_bytes count
- discard
return str.split("::").inject(Object) { |a,n| a.const_get(n) }
- when ?p
+ when 112 # ?p
count = next_string.to_i
obj = Tuple.new(count)
i = 0
@@ -159,7 +156,7 @@ def unmarshal_data
i += 1
end
return obj
- when ?i
+ when 105 # ?i
count = next_string.to_i
seq = InstructionSequence.new(count)
i = 0
@@ -168,11 +165,11 @@ def unmarshal_data
i += 1
end
return seq
- when ?E
+ when 69 # ?E
count = next_string.to_i
name = next_bytes count
return Encoding.find(name) if defined?(Encoding)
- when ?M
+ when 77 # ?M
version = next_string.to_i
if version != 1
raise "Unknown CompiledMethod version #{version}"
@@ -229,34 +226,17 @@ def next_string
private :next_string
##
- # Returns the next _count_ bytes in _@data_.
+ # Returns the next _count_ bytes in _@data_, skipping the
+ # trailing "\n" character.
def next_bytes(count)
str = String.from_bytearray @data, @start, count
- @start += count
+ @start += count + 1
str
end
private :next_bytes
##
- # Returns the next byte in _@data_.
- def next_byte
- byte = @data[@start]
- @start += 1
- byte
- end
-
- private :next_byte
-
- ##
- # Moves the next read pointer ahead by one character.
- def discard
- @start += 1
- end
-
- private :discard
-
- ##
# For object +val+, return a String represetation.
def marshal(val)
@@ -0,0 +1,79 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "Rubinius::CompiledFile::Marshal#unmarshal" do
+ it "unmarshals true" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("t\n").should == true
+ end
+
+ it "unmarshals false" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("f\n").should == false
+ end
+
+ it "unmarshals nil" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("n\n").should == nil
+ end
+
+ it "unmarshals an Integer" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("I\nCAFEF00D").should == 0xCAFEF00D
+ end
+
+ it "unmarshals a Float" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\n +0.785000000000000031086244689504383131861686706542968750 2\n").should == 3.14
+ end
+
+ it "unmarshals +infinity" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\nInfinity\n").should be_positive_infinity
+ end
+
+ it "unmarshals -infinity" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\n-Infinity\n").should be_negative_infinity
+ end
+
+ it "unmarshals NaN" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("d\nNaN\n").should be_nan
+ end
+
+ it "unmarshals a Symbol" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("x\n12\nHello world!\n").should == :"Hello world!"
+ end
+
+ it "unmarshals a constant" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("c\n22\nRubinius::CompiledFile\n").should == Rubinius::CompiledFile
+ end
+
+ ruby_version_is ""..."1.9" do
+ it "unmarshals a String" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("s\nE\n0\n\n12\nHello world!\n").should == "Hello world!"
+ end
+
+ it "returns nil when unmarshalling an encoding" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("E\n5\nUTF-8\n13\n").should be_nil
+ end
+ end
+
+ ruby_version_is "1.9" do
+ it "unmarshals a String" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ str = marshal.unmarshal("s\nE\n5\nUTF-8\n12\nHello world!\n")
+ str.should == "Hello world!"
+ str.encoding.should == Encoding::UTF_8
+ end
+
+ it "unmarshals an encoding" do
+ marshal = Rubinius::CompiledFile::Marshal.new
+ marshal.unmarshal("E\n5\nUTF-8\n13\n").should == Encoding::UTF_8
+ end
+ end
+end
@@ -34,9 +34,5 @@ def o.f
end
o.f.should == 2
end
-
- it "raises a SyntaxError when the block contains a retry statement" do
- lambda { eval 'Fiber.new { retry; }' }.should raise_error(SyntaxError)
- end
end
end
@@ -6,6 +6,7 @@
12345.to_s(8).should == "30071"
12345.to_s(10).should == "12345"
12345.to_s(16).should == "3039"
+ 95.to_s(16).should == "5f"
12345.to_s(36).should == "9ix"
end
@@ -4,16 +4,35 @@
describe "Process.detach" do
platform_is_not :windows do
it "returns a thread" do
- p1 = Process.fork { Process.exit! }
- Process.detach(p1).should be_kind_of(Thread)
+ pid = Process.fork { Process.exit! }
+ Process.detach(pid).should be_kind_of(Thread)
+ end
+
+ it "produces the exit Process::Status as the thread value" do
+ pid = Process.fork { Process.exit! }
+ status = Process.detach(pid).value
+ status.should be_kind_of(Process::Status)
+ status.pid.should == pid
end
platform_is_not :openbsd do
it "reaps the child process's status automatically" do
- p1 = Process.fork { Process.exit! }
- th = Process.detach(p1)
+ pid = Process.fork { Process.exit! }
+ th = Process.detach(pid)
timeout(3) { th.join }
- lambda { Process.waitpid(p1) }.should raise_error(Errno::ECHILD)
+ lambda { Process.waitpid(pid) }.should raise_error(Errno::ECHILD)
+ end
+ end
+
+ ruby_version_is "1.9" do
+ it "sets the :pid thread-local to the PID" do
+ pid = Process.fork { Process.exit! }
+ Process.detach(pid)[:pid].should == pid
+ end
+
+ it "provides a #pid method on the returned thread which returns the PID" do
+ pid = Process.fork { Process.exit! }
+ Process.detach(pid).pid.should == pid
end
end
end
Oops, something went wrong.

0 comments on commit 03248a9

Please sign in to comment.