Permalink
Browse files

A bunch of fixes found while working on Socket

  • Loading branch information...
evanphx committed Jan 11, 2008
1 parent 2828a28 commit 76846154773a87bc8d99c97e91250abda22f6378
View
@@ -585,12 +585,27 @@ file 'runtime/platform.conf' do |t|
SEEK_CUR
SEEK_END
}
+
+ socket_constants = %w{
+ AF_UNIX
+ AF_LOCAL
+ AF_INET
+ SOCK_STREAM
+ SOCK_DGRAM
+ SOCK_RAW
+ SOCK_RDM
+ SOCK_SEQPACKET
+ SO_REUSEADDR
+ SOL_SOCKET
+ }
cg = ConstGenerator.new
cg.include "stdio.h"
cg.include "fcntl.h"
+ cg.include "sys/socket.h"
file_constants.each { |c| cg.const c }
io_constants.each { |c| cg.const c }
+ socket_constants.each { |c| cg.const c }
cg.calculate
puts "Generating #{t.name}..."
@@ -607,6 +622,11 @@ file 'runtime/platform.conf' do |t|
const = cg.constants[name]
f.puts "rbx.platform.io.#{name} = #{const.converted_value}"
end
+
+ socket_constants.each do |name|
+ const = cg.constants[name]
+ f.puts "rbx.platform.socket.#{name} = #{const.converted_value}"
+ end
end
end
View
@@ -92,11 +92,11 @@ def initialize(fd)
raise Errno::EBADF, "invalid descriptor"
end
- @descriptor = desc
- setup
+ setup(desc)
end
- def setup
+ def setup(desc=nil)
+ @descriptor = desc if desc
@buffer = IO::Buffer.new(BufferSize)
@eof = false
@lineno = 0
@@ -112,6 +112,12 @@ def eof?
@eof
end
+ def wait_til_readable
+ chan = Channel.new
+ Scheduler.send_on_readable chan, self, nil, nil
+ chan.receive
+ end
+
def __ivars__ ; @__ivars__ ; end
def inspect
View
@@ -70,8 +70,12 @@ def initialize(*args)
@lock.send nil
end
- if Thread.abort_on_exception
- Thread.main.raise @exception
+ if @exception
+ if Thread.abort_on_exception
+ Thread.main.raise @exception
+ elsif $DEBUG
+ STDERR.puts "Exception in thread: #{@exception.message} (#{@exception.class})"
+ end
end
end
end
View
@@ -38,7 +38,20 @@
if thr == Thread.current
thr = Thread.main
end
-
+
+ # The current thread might be dead if all other live threads are
+ # a sleep when the current one died.
+ unless thr.alive?
+
+ thr = Thread.main
+ # If main is dead too. Wow. Ok.. well... tell the user.
+ unless thr.alive?
+ puts "Signal received, but the main thread is dead."
+ puts "Unable to continue."
+ exit! 1
+ end
+ end
+
# Push the output down a little bit, makes things look more
# obvious that the system was interrupted.
puts
View
@@ -158,6 +158,10 @@ def self.size_to_type(size)
# Be like C, use int as the default type size.
return :int
end
+
+ def self.config(name)
+ ::RUBY_CONFIG["rbx.platform.#{name}"]
+ end
end
View
@@ -8,10 +8,14 @@ def self.do_not_reverse_lookup
end
def initialize(domain, type, protocol)
- fd = Socket::Foreign.create_socket(domain.to_i, type.to_i, protocol.to_i)
- Errno.handle if fd < 0
-
- super(fd)
+ # TCPSocket hits here already setup (the class inheritance
+ # for socket is busted, thats why we have this.)
+ unless descriptor
+ fd = Socket::Foreign.create_socket(domain.to_i, type.to_i, protocol.to_i)
+ Errno.handle if fd < 0
+
+ super(fd)
+ end
@domain = domain
@type = type
@@ -28,7 +32,7 @@ def setsockopt(level, optname, optval)
if optval.is_a?(Fixnum)
MemoryPointer.new :int do |val|
val.write_int optval
- error = Socket::Foreign.set_socket_option(@descriptor, level, optname, val, optval.size)
+ error = Socket::Foreign.set_socket_option(descriptor, level, optname, val, val.size)
end
elsif optval.is_a?(String)
raise NotImplementedError
@@ -46,30 +50,20 @@ def setsockopt(level, optname, optval)
class Socket < BasicSocket
module Constants
- AF_UNIX = 1
- AF_LOCAL = 1
- AF_INET = 2
+ AF_UNIX = FFI.config('socket.AF_UNIX')
+ AF_LOCAL = FFI.config('socket.AF_LOCAL')
+ AF_INET = FFI.config('socket.AF_INET')
AI_PASSIVE = 1
- SOCK_STREAM = 1
- SOCK_DGRAM = 2
- SOCK_RAW = 3
- SOCK_RDM = 4
- SOCK_SEQPACKET = 5
-
- SO_ACCEPTFILTER = 4096
-
- SOL_TCP = 6
+ SOCK_STREAM = FFI.config('socket.SOCK_STREAM')
+ SOCK_DGRAM = FFI.config('socket.SOCK_DGRAM')
+ SOCK_RAW = FFI.config('socket.SOCK_RAW')
+ SOCK_RDM = FFI.config('socket.SOCK_RDM')
+ SOCK_SEQPACKET = FFI.config('socket.SOCK_SEQPACKET')
- case RUBY_PLATFORM
- when /linux/
- SOL_SOCKET = 1
- SO_REUSEADDR = 2
- else
- SOL_SOCKET = 65535 # TODO - Different on weird platforms
- SO_REUSEADDR = 4
- end
+ SOL_SOCKET = FFI.config('socket.SOL_SOCKET')
+ SO_REUSEADDR = FFI.config('socket.SO_REUSEADDR')
end
module Foreign
@@ -82,6 +76,8 @@ module Foreign
attach_function "ffi_pack_sockaddr_un", :pack_sa_unix, [:state, :string], :object
attach_function "ffi_pack_sockaddr_in", :pack_sa_ip, [:state, :string, :string, :int, :int], :object
attach_function "ffi_getpeername", :getpeername, [:state, :int, :int], :object
+ attach_function "ffi_getsockname", :getsockname, [:state, :int, :int], :object
+ attach_function "ffi_bind", :bind_name, [:int, :string, :string, :int], :int
end
include Socket::Constants
@@ -93,6 +89,7 @@ def self.pack_sockaddr_in(port, host, type = 0, flags = 0)
class << self
alias_method :sockaddr_in, :pack_sockaddr_in
end
+
end
class UNIXSocket < BasicSocket
@@ -115,53 +112,79 @@ def initialize(kind, protocol=0)
def peeraddr
reverse = BasicSocket.do_not_reverse_lookup ? 0 : 1
- name, addr = Socket::Foreign.getpeername descriptor, reverse
+ name, addr, port = Socket::Foreign.getpeername descriptor, reverse
if addr.nil?
raise "Unable to get peer address"
end
- ["AF_INET", @port, name, addr]
+ ["AF_INET", port.to_i, name, addr]
end
end
class UDPSocket < IPSocket
- ivar_as_index :descriptor => 1
- def descriptor=(other)
- @descriptor = other
+ def initialize
+ super(Socket::Constants::SOCK_DGRAM)
end
- def initialize(host, port)
- super(Socket::Constants::SOCK_DGRAM)
-
- @host = host
+ def bind(host, port)
@port = port
+ @host = host
+
+ ret = Socket::Foreign.bind_name(descriptor, @host.to_s, @port.to_s, @type.to_i)
+ Errno.handle if ret != 0
+
+ return
+
+ p :bind => [host, port]
@sockaddr = Socket.pack_sockaddr_in(@port, @host, @type)
- ret = Socket::Foreign.connect_socket(descriptor, @sockaddr, @sockaddr.size)
+ p :sockaddr => [descriptor, @sockaddr]
+ ret = Socket::Foreign.bind_socket(descriptor, @sockaddr, @sockaddr.size)
+ p :ret => ret
Errno.handle if ret != 0
end
def inspect
"#<#{self.class}:0x#{object_id.to_s(16)} #{@host}:#{@port}>"
end
+
end
class TCPSocket < IPSocket
- ivar_as_index :descriptor => 1
- def descriptor=(other)
- @descriptor = other
+
+ def self.from_descriptor(fixnum)
+ sock = allocate()
+ sock.from_descriptor(fixnum)
+ return sock
end
-
+
+ def from_descriptor(fixnum)
+ setup(fixnum)
+
+ @connected = true
+
+ name, addr, port = Socket::Foreign.getpeername fixnum, 0
+
+ initialize(addr, port)
+
+ return self
+ end
+
def initialize(host, port)
super(Socket::Constants::SOCK_STREAM)
@host = host
@port = port
- @sockaddr = Socket.pack_sockaddr_in(@port, @host, @type)
+ @connected ||= false
- ret = Socket::Foreign.connect_socket(descriptor, @sockaddr, @sockaddr.size)
- Errno.handle if ret != 0
+ unless @connected
+ @sockaddr = Socket.pack_sockaddr_in(@port, @host, @type)
+
+ ret = Socket::Foreign.connect_socket(descriptor, @sockaddr, @sockaddr.size)
+ Errno.handle if ret != 0
+ @connected = true
+ end
end
def inspect
@@ -170,7 +193,6 @@ def inspect
end
class TCPServer < TCPSocket
- ivar_as_index :descriptor => 1
def initialize(host, port = nil)
if host.kind_of?(Fixnum) then
port = host
@@ -187,13 +209,19 @@ def initialize(host, port = nil)
Errno.handle "Unable to create socket"
end
- @descriptor = fd
- setsockopt(Socket::Constants::SOL_SOCKET, Socket::Constants::SO_REUSEADDR, true)
+ setup(fd)
+
+ begin
+ setsockopt(Socket::Constants::SOL_SOCKET, Socket::Constants::SO_REUSEADDR, true)
+ rescue SystemCallError
+ # MRI's socket.c tries this but never checks the return value, so
+ # just eat any error.
+ end
@sockaddr = Socket.pack_sockaddr_in(@port, @host, @type,
Socket::Constants::AI_PASSIVE)
- ret = Socket::Foreign.bind_socket(@descriptor, @sockaddr, @sockaddr.size)
+ ret = Socket::Foreign.bind_socket(descriptor, @sockaddr, @sockaddr.size)
Errno.handle if ret != 0
ret = Socket::Foreign.listen_socket(fd, 5)
@@ -204,27 +232,27 @@ def initialize(host, port = nil)
def accept
return if closed?
+ wait_til_readable()
+
fd = -1
size = 0
MemoryPointer.new :int do |sz|
sz.write_int @sockaddr.size # initialize to the 'expected' size
- fd = Socket::Foreign.accept @descriptor, @sockaddr, sz
+ fd = Socket::Foreign.accept descriptor, @sockaddr, sz
size = sz.read_int
end
+
if fd < 0
Errno.handle "Unable to accept on socket"
end
- socket = TCPSocket.allocate
- socket.descriptor = fd
-
- socket
+ TCPSocket.from_descriptor(fd)
end
def listen(log)
log = Type.coerce_to(log, Fixnum, :to_int)
- ret = Socket::Foreign.listen_socket(@descriptor, log)
+ ret = Socket::Foreign.listen_socket(descriptor, log)
if ret != 0
Errno.handle
end
View
@@ -241,6 +241,7 @@ void cpu_channel_register(STATE, cpu c, OBJECT self, OBJECT cur_thr);
void cpu_task_set_outstanding(STATE, OBJECT self, OBJECT ary);
void cpu_event_setup_children(STATE, cpu c);
void cpu_event_wait_child(STATE, cpu c, OBJECT channel, int pid, int flags);
+void cpu_event_clear(STATE, int fd);
#define channel_set_waiting(obj, val) SET_FIELD(obj, 1, val)
#define channel_get_waiting(obj) NTH_FIELD(obj, 1)
Oops, something went wrong.

0 comments on commit 7684615

Please sign in to comment.