Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

A bunch of fixes found while working on Socket

  • Loading branch information...
commit 76846154773a87bc8d99c97e91250abda22f6378 1 parent 2828a28
@evanphx evanphx authored
View
20 Rakefile
@@ -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
12 kernel/core/io.rb
@@ -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
8 kernel/core/thread.rb
@@ -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
15 kernel/loader.rb
@@ -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
4 kernel/platform/ffi.rb
@@ -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
132 lib/socket.rb
@@ -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
1  shotgun/lib/cpu.h
@@ -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)
View
73 shotgun/lib/cpu_event.c
@@ -33,6 +33,7 @@ struct thread_info {
OBJECT buffer;
int count;
pid_t pid;
+ int fd;
union {
int options;
int sig;
@@ -49,6 +50,7 @@ void cpu_event_init(STATE) {
setenv("EVENT_NOPOLL", "1", 1);
#endif
state->event_base = event_init();
+ state->thread_infos = NULL;
}
void cpu_event_run(STATE) {
@@ -75,28 +77,69 @@ void cpu_event_each_channel(STATE, OBJECT (*cb)(STATE, void*, OBJECT), void *cb_
void _cpu_event_register_info(STATE, struct thread_info *ti) {
state->pending_events++;
ti->prev = NULL;
- ti->next = state->thread_infos ? state->thread_infos : NULL;
+ ti->next = state->thread_infos;
+ if(state->thread_infos) {
+ ((struct thread_info*)state->thread_infos)->prev = ti;
+ }
state->thread_infos = ti;
}
void _cpu_event_unregister_info(STATE, struct thread_info *ti) {
- if(!ti->prev) {
- if(ti->next) {
- state->thread_infos = ti->next;
- ti->next->prev = NULL;
+ struct thread_info *next, *prev;
+
+ next = ti->next;
+ prev = ti->prev;
+
+ if(next) {
+ next->prev = prev;
+ }
+
+ if(prev) {
+ prev->next = next;
+ }
+
+ if(next) {
+ if(next->next == prev) {
+ next->next = NULL;
+ }
+ }
+
+ if(prev) {
+ if(prev->prev == next) {
+ prev->prev = NULL;
+ }
+ }
+
+ if(state->thread_infos == ti) {
+ if(next) {
+ state->thread_infos = next;
+ } else if(prev) {
+ state->thread_infos = prev;
} else {
state->thread_infos = NULL;
}
- } else {
- ti->prev->next = ti->next;
- if(ti->next) {
- ti->next->prev = ti->prev;
- }
}
-
+
event_del(&ti->ev);
state->pending_events--;
- event_del(&ti->ev);
+}
+
+void cpu_event_clear(STATE, int fd) {
+ struct thread_info *ti = (struct thread_info*)state->thread_infos;
+ struct thread_info *tnext;
+
+ if(fd <= 0) return;
+
+ while(ti) {
+ tnext = ti->next;
+ if(ti->fd == fd) {
+ cpu_channel_send(state, ti->c, ti->channel, Qnil);
+ _cpu_event_unregister_info(state, ti);
+ XFREE(ti);
+ }
+ ti = tnext;
+ }
+
}
void _cpu_wake_channel(int fd, short event, void *arg) {
@@ -197,6 +240,7 @@ void cpu_event_wake_channel(STATE, cpu c, OBJECT channel, struct timeval *tv) {
struct thread_info *ti;
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = 0;
ti->state = state;
ti->c = c;
ti->channel = channel;
@@ -211,6 +255,7 @@ void cpu_event_wait_readable(STATE, cpu c, OBJECT channel, int fd, OBJECT buffer
struct thread_info *ti;
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = fd;
ti->state = state;
ti->c = c;
ti->channel = channel;
@@ -241,6 +286,7 @@ void cpu_event_wait_writable(STATE, cpu c, OBJECT channel, int fd) {
struct thread_info *ti;
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = fd;
ti->state = state;
ti->c = c;
ti->channel = channel;
@@ -282,6 +328,7 @@ void cpu_event_wait_signal(STATE, cpu c, OBJECT channel, int sig) {
be delivered to either an old handler or the new handler. */
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = 0;
ti->type = SIGNAL;
ti->state = state;
ti->c = c;
@@ -345,6 +392,7 @@ void cpu_event_wait_child(STATE, cpu c, OBJECT channel, int pid, int flags) {
struct thread_info *ti;
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = 0;
ti->state = state;
ti->c = c;
ti->pid = pid;
@@ -359,6 +407,7 @@ void cpu_event_setup_children(STATE, cpu c) {
struct thread_info *ti;
ti = ALLOC_N(struct thread_info, 1);
+ ti->fd = 0;
ti->state = state;
ti->c = c;
signal_set(&ti->ev, SIGCHLD, _cpu_find_waiters_cb, (void*)ti);
View
33 shotgun/lib/cpu_task.c
@@ -16,6 +16,8 @@
#include "shotgun/lib/array.h"
#include "shotgun/lib/object.h"
+void cpu_thread_dequeue(STATE, OBJECT thr);
+
void cpu_task_cleanup(STATE, OBJECT self) {
struct cpu_task *task;
@@ -155,9 +157,8 @@ int cpu_task_alive_p(STATE, OBJECT self) {
task = (struct cpu_task*)BYTES_OF(self);
- if(NIL_P(task->active_context) || NIL_P(task->home_context)) {
- return FALSE;
- }
+ if(!REFERENCE_P(task->active_context)) return FALSE;
+ if(!REFERENCE_P(task->home_context)) return FALSE;
return TRUE;
}
@@ -179,6 +180,8 @@ int cpu_task_select(STATE, cpu c, OBJECT nw) {
struct cpu_task *cur_task, *new_task, *ct;
OBJECT home, cur;
+ assert(cpu_task_alive_p(state, nw));
+
if(c->active_context != Qnil) {
cpu_save_registers(state, c, 0);
}
@@ -211,9 +214,9 @@ int cpu_task_select(STATE, cpu c, OBJECT nw) {
assert(cur_task->sp_ptr >= cur_task->stack_top);
if(REFERENCE_P(cur_task->active_context)) {
assert(cur_task->active_context->obj_type == MContextType ||
- cur_task->active_context->obj_type == BContextType);
+ cur_task->active_context->obj_type == BContextType);
+
}
-
if(REFERENCE_P(cur_task->home_context)) {
assert(cur_task->home_context->obj_type == MContextType ||
cur_task->home_context->obj_type == BContextType);
@@ -341,6 +344,7 @@ OBJECT cpu_thread_get_task(STATE, OBJECT self) {
void cpu_thread_exited(STATE, cpu c) {
thread_set_task(c->current_thread, Qnil);
+ cpu_thread_dequeue(state, c->current_thread);
cpu_thread_run_best(state, c);
}
@@ -348,8 +352,11 @@ int cpu_thread_alive_p(STATE, OBJECT self) {
OBJECT task;
task = thread_get_task(self);
- if(NIL_P(task)) return FALSE;
- return cpu_task_alive_p(state, task);
+ if(NIL_P(task)) {
+ return FALSE;
+ } else {
+ return cpu_task_alive_p(state, task);
+ }
}
void cpu_thread_schedule(STATE, OBJECT self) {
@@ -376,7 +383,7 @@ void cpu_thread_schedule(STATE, OBJECT self) {
OBJECT cpu_thread_find_highest(STATE) {
int i, t;
- OBJECT lst, tup;
+ OBJECT lst, tup, thr;
cpu_event_update(state);
@@ -387,7 +394,10 @@ OBJECT cpu_thread_find_highest(STATE) {
lst = tuple_at(state, tup, i);
if(FIXNUM_TO_INT(list_get_count(lst)) != 0) {
state->pending_threads--;
- return list_shift(state, lst);
+ thr = list_shift(state, lst);
+ /* It's a bug that a dead thread shows up as queued.
+ * But for now, just check again here, it's safer anyway. */
+ if(cpu_thread_alive_p(state, thr)) return thr;
}
}
// printf("Nothing to do, waiting for events.\n");
@@ -426,7 +436,9 @@ void cpu_thread_switch(STATE, cpu c, OBJECT thr) {
the already running thread (via the current thread waiting
for an event), and we thus don't need to restore it. */
if(thr == c->current_thread) return;
-
+
+ assert(cpu_thread_alive_p(state, thr));
+
object_set_ivar(state, thr, SYM("@sleep"), Qfalse);
/* Save the current task back into the current thread, in case
@@ -441,6 +453,7 @@ void cpu_thread_run_best(STATE, cpu c) {
OBJECT thr;
thr = cpu_thread_find_highest(state);
+ assert(cpu_thread_alive_p(state, thr));
cpu_thread_switch(state, c, thr);
}
View
81 shotgun/lib/ffi_util.c
@@ -116,13 +116,18 @@ OBJECT ffi_pack_sockaddr_in(STATE, char *name, char *port, int type, int flags)
int error;
if (type == 0 && flags == 0) {
- type = SOCK_DGRAM;
- }
+ type = SOCK_DGRAM;
+ }
+
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = type;
hints.ai_flags = flags;
+ if(strlen(name) == 0) {
+ name = NULL;
+ }
+
error = getaddrinfo(name, port, &hints, &res);
if(error) {
printf("ERROR: %s\n", gai_strerror(error));
@@ -136,25 +141,16 @@ OBJECT ffi_pack_sockaddr_in(STATE, char *name, char *port, int type, int flags)
return ret;
}
-OBJECT ffi_getpeername(STATE, int s, int reverse_lookup) {
+OBJECT ffi_decode_sockaddr(STATE, struct sockaddr *addr, int len, int reverse_lookup) {
OBJECT host;
OBJECT address;
int error = 0;
- struct sockaddr_storage addr;
- socklen_t len = sizeof addr;
-
char hbuf[1024];
char pbuf[1024];
- error = getpeername(s, (struct sockaddr*)&addr, &len);
- if(error) {
- printf("ffi_getpeername ERROR: %s\n", gai_strerror(error));
- return Qnil;
- }
-
- error = getnameinfo((struct sockaddr*)&addr, len, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+ error = getnameinfo(addr, len, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
if(error) {
printf("ffi_getpeername ERROR: %s\n", gai_strerror(error));
return Qnil;
@@ -162,7 +158,7 @@ OBJECT ffi_getpeername(STATE, int s, int reverse_lookup) {
address = string_new(state, hbuf);
if(reverse_lookup) {
- error = getnameinfo((struct sockaddr*)&addr, len, hbuf, sizeof(hbuf), NULL, 0, 0);
+ error = getnameinfo(addr, len, hbuf, sizeof(hbuf), NULL, 0, 0);
if(error) {
printf("ffi_getpeername ERROR: %s\n", gai_strerror(error));
return Qnil;
@@ -171,7 +167,49 @@ OBJECT ffi_getpeername(STATE, int s, int reverse_lookup) {
host = string_new(state, hbuf);
- return tuple_new2(state, 2, host, address);
+ return tuple_new2(state, 3, host, address, string_new(state, pbuf));
+}
+
+OBJECT ffi_getpeername(STATE, int s, int reverse_lookup) {
+ OBJECT host;
+ OBJECT address;
+
+ int error = 0;
+
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof addr;
+
+ char hbuf[1024];
+ char pbuf[1024];
+
+ error = getpeername(s, (struct sockaddr*)&addr, &len);
+ if(error) {
+ printf("ffi_getpeername ERROR: %s\n", gai_strerror(error));
+ return Qnil;
+ }
+
+ return ffi_decode_sockaddr(state, (struct sockaddr*)&addr, len, reverse_lookup);
+}
+
+OBJECT ffi_getsockname(STATE, int s, int reverse_lookup) {
+ OBJECT host;
+ OBJECT address;
+
+ int error = 0;
+
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof addr;
+
+ char hbuf[1024];
+ char pbuf[1024];
+
+ error = getsockname(s, (struct sockaddr*)&addr, &len);
+ if(error) {
+ printf("ffi_getsockname ERROR: %s\n", gai_strerror(error));
+ return Qnil;
+ }
+
+ return ffi_decode_sockaddr(state, (struct sockaddr*)&addr, len, reverse_lookup);
}
/*
@@ -184,7 +222,9 @@ int ffi_bind(int s, struct sockaddr *name, socklen_t len) {
return ret;
}
-int ffi_bind_local_socket(int s) {
+*/
+
+int ffi_bind(int s, char *host, char *port, int type) {
struct addrinfo hints;
struct addrinfo *res = NULL;
int error;
@@ -192,18 +232,19 @@ int ffi_bind_local_socket(int s) {
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
+ hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
+
+ if(strlen(host) == 0) host = NULL;
- error = getaddrinfo(0, 0, &hints, &res);
+ error = getaddrinfo(NULL, "40011", &hints, &res);
if(error) {
printf("bind_local_socket ERROR: %s\n", gai_strerror(error));
- return Qnil;
+ return -1;
}
ret = bind(s, res->ai_addr, res->ai_addrlen);
return ret;
}
-*/
void *ffi_add_ptr(char *ptr, int offset) {
return (void*)(ptr + offset);
View
28 shotgun/lib/primitives.rb
@@ -498,6 +498,7 @@ def io_close
if( close(j) ) {
stack_push(Qfalse);
} else {
+ cpu_event_clear(state, j);
io_set_descriptor(self, I2N(-1));
stack_push(Qtrue);
}
@@ -2333,17 +2334,22 @@ def thread_raise
GUARD( RISA(self, thread) );
t1 = stack_pop();
-
- /* The return value */
- stack_push(Qnil);
-
- cpu_thread_schedule(state, c->current_thread);
- cpu_thread_force_run(state, c, self);
-
- methctx_reference(state, c->active_context);
- exception_set_context(t1, c->active_context);
-
- cpu_raise_exception(state, c, t1);
+
+ if(!cpu_thread_alive_p(state, self)) {
+ stack_push(Qfalse);
+ } else {
+
+ /* The return value */
+ stack_push(Qtrue);
+
+ cpu_thread_schedule(state, c->current_thread);
+ cpu_thread_force_run(state, c, self);
+
+ methctx_reference(state, c->active_context);
+ exception_set_context(t1, c->active_context);
+
+ cpu_raise_exception(state, c, t1);
+ }
CODE
end
View
19 spec/ruby/1.8/library/socket/accept_spec.rb
@@ -7,18 +7,19 @@
@server = TCPServer.new('127.0.0.1', SocketSpecs.port)
@read = false
@thread = Thread.new do
- begin
- client = @server.accept_nonblock
- rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
- @listening = true
- IO.select([@server])
- retry
- end
+ @listening = true
+ client = @server.accept
@data << client.read(5)
+ client << "hello"
@read = true
client.close
end
- Thread.pass until @listening
+
+ while @thread.status and !@listening
+ sleep 0.2
+ Thread.pass
+ end
+ sleep 0.2
end
after(:each) do
@@ -29,7 +30,7 @@
it "accepts what is written by the client" do
@socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
@socket.write('hello')
- Thread.pass until @read
+ out = @socket.read(5)
@thread.join
@data.should == ['hello']
end
View
2  spec/ruby/1.8/library/socket/fixtures/classes.rb
@@ -2,6 +2,6 @@
module SocketSpecs
def self.port
- 40000
+ 40001
end
end
View
13 spec/ruby/1.8/library/socket/open_spec.rb
@@ -12,22 +12,27 @@
@ready = false
server_thread = Thread.new do
@server = UDPSocket.open
- @server.bind(nil,SocketSpecs.port)
+ begin
+ @server.bind(nil,SocketSpecs.port)
+ rescue Object => e
+ puts "unable to bind."
+ raise e
+ end
@ready = true
msg1 = @server.recvfrom(64)
msg1[0].should == "ad hoc"
msg1[1][0].should == "AF_INET"
- (msg1[1][1].kind_of? Fixnum).should == true
+ msg1[1][1].should be_kind_of(Fixnum)
msg1[1][3].should == "127.0.0.1"
msg2 = @server.recvfrom(64)
msg2[0].should == "connection-based"
msg2[1][0].should == "AF_INET"
- (msg2[1][1].kind_of? Fixnum).should == true
+ msg2[1][1].should be_kind_of(Fixnum)
msg2[1][3].should == "127.0.0.1"
end
- Thread.pass until @ready
+ Thread.pass while server_thread.status and !@ready
UDPSocket.open.send("ad hoc", 0, 'localhost',SocketSpecs.port)
Please sign in to comment.
Something went wrong with that request. Please try again.