diff options
Diffstat (limited to 'ext/socket')
-rw-r--r-- | ext/socket/ancdata.c | 4 | ||||
-rw-r--r-- | ext/socket/depend | 345 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 25 | ||||
-rw-r--r-- | ext/socket/getaddrinfo.c | 3 | ||||
-rw-r--r-- | ext/socket/init.c | 82 | ||||
-rw-r--r-- | ext/socket/lib/socket.rb | 539 | ||||
-rw-r--r-- | ext/socket/mkconstants.rb | 46 | ||||
-rw-r--r-- | ext/socket/raddrinfo.c | 529 | ||||
-rw-r--r-- | ext/socket/rubysocket.h | 6 | ||||
-rw-r--r-- | ext/socket/socket.c | 5 | ||||
-rw-r--r-- | ext/socket/unixsocket.c | 2 |
11 files changed, 1431 insertions, 155 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index 7406177de2..6ef040b692 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -1555,6 +1555,10 @@ bsock_recvmsg_internal(VALUE sock, ss = rb_recvmsg(fptr->fd, &mh, flags); + if (ss == 0 && !rsock_is_dgram(fptr)) { + return Qnil; + } + if (ss == -1) { int e; if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) { diff --git a/ext/socket/depend b/ext/socket/depend index 28c5540cd6..750bb0734f 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -13,6 +13,7 @@ constdefs.c: constdefs.h ancdata.o: $(RUBY_EXTCONF_H) ancdata.o: $(arch_hdrdir)/ruby/config.h ancdata.o: $(hdrdir)/ruby/assert.h +ancdata.o: $(hdrdir)/ruby/atomic.h ancdata.o: $(hdrdir)/ruby/backward.h ancdata.o: $(hdrdir)/ruby/backward/2/assume.h ancdata.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -65,6 +66,7 @@ ancdata.o: $(hdrdir)/ruby/internal/attr/noexcept.h ancdata.o: $(hdrdir)/ruby/internal/attr/noinline.h ancdata.o: $(hdrdir)/ruby/internal/attr/nonnull.h ancdata.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ancdata.o: $(hdrdir)/ruby/internal/attr/packed_struct.h ancdata.o: $(hdrdir)/ruby/internal/attr/pure.h ancdata.o: $(hdrdir)/ruby/internal/attr/restrict.h ancdata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -133,7 +135,6 @@ ancdata.o: $(hdrdir)/ruby/internal/intern/enumerator.h ancdata.o: $(hdrdir)/ruby/internal/intern/error.h ancdata.o: $(hdrdir)/ruby/internal/intern/eval.h ancdata.o: $(hdrdir)/ruby/internal/intern/file.h -ancdata.o: $(hdrdir)/ruby/internal/intern/gc.h ancdata.o: $(hdrdir)/ruby/internal/intern/hash.h ancdata.o: $(hdrdir)/ruby/internal/intern/io.h ancdata.o: $(hdrdir)/ruby/internal/intern/load.h @@ -164,12 +165,12 @@ ancdata.o: $(hdrdir)/ruby/internal/memory.h ancdata.o: $(hdrdir)/ruby/internal/method.h ancdata.o: $(hdrdir)/ruby/internal/module.h ancdata.o: $(hdrdir)/ruby/internal/newobj.h -ancdata.o: $(hdrdir)/ruby/internal/rgengc.h ancdata.o: $(hdrdir)/ruby/internal/scan_args.h ancdata.o: $(hdrdir)/ruby/internal/special_consts.h ancdata.o: $(hdrdir)/ruby/internal/static_assert.h ancdata.o: $(hdrdir)/ruby/internal/stdalign.h ancdata.o: $(hdrdir)/ruby/internal/stdbool.h +ancdata.o: $(hdrdir)/ruby/internal/stdckdint.h ancdata.o: $(hdrdir)/ruby/internal/symbol.h ancdata.o: $(hdrdir)/ruby/internal/value.h ancdata.o: $(hdrdir)/ruby/internal/value_type.h @@ -184,27 +185,46 @@ ancdata.o: $(hdrdir)/ruby/ruby.h ancdata.o: $(hdrdir)/ruby/st.h ancdata.o: $(hdrdir)/ruby/subst.h ancdata.o: $(hdrdir)/ruby/thread.h +ancdata.o: $(hdrdir)/ruby/thread_native.h ancdata.o: $(hdrdir)/ruby/util.h +ancdata.o: $(hdrdir)/ruby/version.h +ancdata.o: $(top_srcdir)/ccan/check_type/check_type.h +ancdata.o: $(top_srcdir)/ccan/container_of/container_of.h +ancdata.o: $(top_srcdir)/ccan/list/list.h +ancdata.o: $(top_srcdir)/ccan/str/str.h ancdata.o: $(top_srcdir)/internal.h ancdata.o: $(top_srcdir)/internal/array.h +ancdata.o: $(top_srcdir)/internal/basic_operators.h ancdata.o: $(top_srcdir)/internal/compilers.h ancdata.o: $(top_srcdir)/internal/error.h ancdata.o: $(top_srcdir)/internal/gc.h +ancdata.o: $(top_srcdir)/internal/imemo.h ancdata.o: $(top_srcdir)/internal/io.h +ancdata.o: $(top_srcdir)/internal/sanitizers.h ancdata.o: $(top_srcdir)/internal/serial.h ancdata.o: $(top_srcdir)/internal/static_assert.h ancdata.o: $(top_srcdir)/internal/string.h ancdata.o: $(top_srcdir)/internal/thread.h ancdata.o: $(top_srcdir)/internal/vm.h ancdata.o: $(top_srcdir)/internal/warnings.h +ancdata.o: $(top_srcdir)/method.h +ancdata.o: $(top_srcdir)/node.h +ancdata.o: $(top_srcdir)/ruby_assert.h +ancdata.o: $(top_srcdir)/ruby_atomic.h +ancdata.o: $(top_srcdir)/rubyparser.h ancdata.o: $(top_srcdir)/shape.h +ancdata.o: $(top_srcdir)/thread_pthread.h +ancdata.o: $(top_srcdir)/vm_core.h +ancdata.o: $(top_srcdir)/vm_opts.h ancdata.o: ancdata.c ancdata.o: constdefs.h ancdata.o: rubysocket.h ancdata.o: sockport.h +ancdata.o: {$(VPATH)}id.h basicsocket.o: $(RUBY_EXTCONF_H) basicsocket.o: $(arch_hdrdir)/ruby/config.h basicsocket.o: $(hdrdir)/ruby/assert.h +basicsocket.o: $(hdrdir)/ruby/atomic.h basicsocket.o: $(hdrdir)/ruby/backward.h basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h basicsocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -257,6 +277,7 @@ basicsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h basicsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h basicsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h basicsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h basicsocket.o: $(hdrdir)/ruby/internal/attr/pure.h basicsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h basicsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -325,7 +346,6 @@ basicsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h basicsocket.o: $(hdrdir)/ruby/internal/intern/error.h basicsocket.o: $(hdrdir)/ruby/internal/intern/eval.h basicsocket.o: $(hdrdir)/ruby/internal/intern/file.h -basicsocket.o: $(hdrdir)/ruby/internal/intern/gc.h basicsocket.o: $(hdrdir)/ruby/internal/intern/hash.h basicsocket.o: $(hdrdir)/ruby/internal/intern/io.h basicsocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -356,12 +376,12 @@ basicsocket.o: $(hdrdir)/ruby/internal/memory.h basicsocket.o: $(hdrdir)/ruby/internal/method.h basicsocket.o: $(hdrdir)/ruby/internal/module.h basicsocket.o: $(hdrdir)/ruby/internal/newobj.h -basicsocket.o: $(hdrdir)/ruby/internal/rgengc.h basicsocket.o: $(hdrdir)/ruby/internal/scan_args.h basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h +basicsocket.o: $(hdrdir)/ruby/internal/stdckdint.h basicsocket.o: $(hdrdir)/ruby/internal/symbol.h basicsocket.o: $(hdrdir)/ruby/internal/value.h basicsocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -376,27 +396,46 @@ basicsocket.o: $(hdrdir)/ruby/ruby.h basicsocket.o: $(hdrdir)/ruby/st.h basicsocket.o: $(hdrdir)/ruby/subst.h basicsocket.o: $(hdrdir)/ruby/thread.h +basicsocket.o: $(hdrdir)/ruby/thread_native.h basicsocket.o: $(hdrdir)/ruby/util.h +basicsocket.o: $(hdrdir)/ruby/version.h +basicsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +basicsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +basicsocket.o: $(top_srcdir)/ccan/list/list.h +basicsocket.o: $(top_srcdir)/ccan/str/str.h basicsocket.o: $(top_srcdir)/internal.h basicsocket.o: $(top_srcdir)/internal/array.h +basicsocket.o: $(top_srcdir)/internal/basic_operators.h basicsocket.o: $(top_srcdir)/internal/compilers.h basicsocket.o: $(top_srcdir)/internal/error.h basicsocket.o: $(top_srcdir)/internal/gc.h +basicsocket.o: $(top_srcdir)/internal/imemo.h basicsocket.o: $(top_srcdir)/internal/io.h +basicsocket.o: $(top_srcdir)/internal/sanitizers.h basicsocket.o: $(top_srcdir)/internal/serial.h basicsocket.o: $(top_srcdir)/internal/static_assert.h basicsocket.o: $(top_srcdir)/internal/string.h basicsocket.o: $(top_srcdir)/internal/thread.h basicsocket.o: $(top_srcdir)/internal/vm.h basicsocket.o: $(top_srcdir)/internal/warnings.h +basicsocket.o: $(top_srcdir)/method.h +basicsocket.o: $(top_srcdir)/node.h +basicsocket.o: $(top_srcdir)/ruby_assert.h +basicsocket.o: $(top_srcdir)/ruby_atomic.h +basicsocket.o: $(top_srcdir)/rubyparser.h basicsocket.o: $(top_srcdir)/shape.h +basicsocket.o: $(top_srcdir)/thread_pthread.h +basicsocket.o: $(top_srcdir)/vm_core.h +basicsocket.o: $(top_srcdir)/vm_opts.h basicsocket.o: basicsocket.c basicsocket.o: constdefs.h basicsocket.o: rubysocket.h basicsocket.o: sockport.h +basicsocket.o: {$(VPATH)}id.h constants.o: $(RUBY_EXTCONF_H) constants.o: $(arch_hdrdir)/ruby/config.h constants.o: $(hdrdir)/ruby/assert.h +constants.o: $(hdrdir)/ruby/atomic.h constants.o: $(hdrdir)/ruby/backward.h constants.o: $(hdrdir)/ruby/backward/2/assume.h constants.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -449,6 +488,7 @@ constants.o: $(hdrdir)/ruby/internal/attr/noexcept.h constants.o: $(hdrdir)/ruby/internal/attr/noinline.h constants.o: $(hdrdir)/ruby/internal/attr/nonnull.h constants.o: $(hdrdir)/ruby/internal/attr/noreturn.h +constants.o: $(hdrdir)/ruby/internal/attr/packed_struct.h constants.o: $(hdrdir)/ruby/internal/attr/pure.h constants.o: $(hdrdir)/ruby/internal/attr/restrict.h constants.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -517,7 +557,6 @@ constants.o: $(hdrdir)/ruby/internal/intern/enumerator.h constants.o: $(hdrdir)/ruby/internal/intern/error.h constants.o: $(hdrdir)/ruby/internal/intern/eval.h constants.o: $(hdrdir)/ruby/internal/intern/file.h -constants.o: $(hdrdir)/ruby/internal/intern/gc.h constants.o: $(hdrdir)/ruby/internal/intern/hash.h constants.o: $(hdrdir)/ruby/internal/intern/io.h constants.o: $(hdrdir)/ruby/internal/intern/load.h @@ -548,12 +587,12 @@ constants.o: $(hdrdir)/ruby/internal/memory.h constants.o: $(hdrdir)/ruby/internal/method.h constants.o: $(hdrdir)/ruby/internal/module.h constants.o: $(hdrdir)/ruby/internal/newobj.h -constants.o: $(hdrdir)/ruby/internal/rgengc.h constants.o: $(hdrdir)/ruby/internal/scan_args.h constants.o: $(hdrdir)/ruby/internal/special_consts.h constants.o: $(hdrdir)/ruby/internal/static_assert.h constants.o: $(hdrdir)/ruby/internal/stdalign.h constants.o: $(hdrdir)/ruby/internal/stdbool.h +constants.o: $(hdrdir)/ruby/internal/stdckdint.h constants.o: $(hdrdir)/ruby/internal/symbol.h constants.o: $(hdrdir)/ruby/internal/value.h constants.o: $(hdrdir)/ruby/internal/value_type.h @@ -568,28 +607,47 @@ constants.o: $(hdrdir)/ruby/ruby.h constants.o: $(hdrdir)/ruby/st.h constants.o: $(hdrdir)/ruby/subst.h constants.o: $(hdrdir)/ruby/thread.h +constants.o: $(hdrdir)/ruby/thread_native.h constants.o: $(hdrdir)/ruby/util.h +constants.o: $(hdrdir)/ruby/version.h +constants.o: $(top_srcdir)/ccan/check_type/check_type.h +constants.o: $(top_srcdir)/ccan/container_of/container_of.h +constants.o: $(top_srcdir)/ccan/list/list.h +constants.o: $(top_srcdir)/ccan/str/str.h constants.o: $(top_srcdir)/internal.h constants.o: $(top_srcdir)/internal/array.h +constants.o: $(top_srcdir)/internal/basic_operators.h constants.o: $(top_srcdir)/internal/compilers.h constants.o: $(top_srcdir)/internal/error.h constants.o: $(top_srcdir)/internal/gc.h +constants.o: $(top_srcdir)/internal/imemo.h constants.o: $(top_srcdir)/internal/io.h +constants.o: $(top_srcdir)/internal/sanitizers.h constants.o: $(top_srcdir)/internal/serial.h constants.o: $(top_srcdir)/internal/static_assert.h constants.o: $(top_srcdir)/internal/string.h constants.o: $(top_srcdir)/internal/thread.h constants.o: $(top_srcdir)/internal/vm.h constants.o: $(top_srcdir)/internal/warnings.h +constants.o: $(top_srcdir)/method.h +constants.o: $(top_srcdir)/node.h +constants.o: $(top_srcdir)/ruby_assert.h +constants.o: $(top_srcdir)/ruby_atomic.h +constants.o: $(top_srcdir)/rubyparser.h constants.o: $(top_srcdir)/shape.h +constants.o: $(top_srcdir)/thread_pthread.h +constants.o: $(top_srcdir)/vm_core.h +constants.o: $(top_srcdir)/vm_opts.h constants.o: constants.c constants.o: constdefs.c constants.o: constdefs.h constants.o: rubysocket.h constants.o: sockport.h +constants.o: {$(VPATH)}id.h ifaddr.o: $(RUBY_EXTCONF_H) ifaddr.o: $(arch_hdrdir)/ruby/config.h ifaddr.o: $(hdrdir)/ruby/assert.h +ifaddr.o: $(hdrdir)/ruby/atomic.h ifaddr.o: $(hdrdir)/ruby/backward.h ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h ifaddr.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -642,6 +700,7 @@ ifaddr.o: $(hdrdir)/ruby/internal/attr/noexcept.h ifaddr.o: $(hdrdir)/ruby/internal/attr/noinline.h ifaddr.o: $(hdrdir)/ruby/internal/attr/nonnull.h ifaddr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h ifaddr.o: $(hdrdir)/ruby/internal/attr/pure.h ifaddr.o: $(hdrdir)/ruby/internal/attr/restrict.h ifaddr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -710,7 +769,6 @@ ifaddr.o: $(hdrdir)/ruby/internal/intern/enumerator.h ifaddr.o: $(hdrdir)/ruby/internal/intern/error.h ifaddr.o: $(hdrdir)/ruby/internal/intern/eval.h ifaddr.o: $(hdrdir)/ruby/internal/intern/file.h -ifaddr.o: $(hdrdir)/ruby/internal/intern/gc.h ifaddr.o: $(hdrdir)/ruby/internal/intern/hash.h ifaddr.o: $(hdrdir)/ruby/internal/intern/io.h ifaddr.o: $(hdrdir)/ruby/internal/intern/load.h @@ -741,12 +799,12 @@ ifaddr.o: $(hdrdir)/ruby/internal/memory.h ifaddr.o: $(hdrdir)/ruby/internal/method.h ifaddr.o: $(hdrdir)/ruby/internal/module.h ifaddr.o: $(hdrdir)/ruby/internal/newobj.h -ifaddr.o: $(hdrdir)/ruby/internal/rgengc.h ifaddr.o: $(hdrdir)/ruby/internal/scan_args.h ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h +ifaddr.o: $(hdrdir)/ruby/internal/stdckdint.h ifaddr.o: $(hdrdir)/ruby/internal/symbol.h ifaddr.o: $(hdrdir)/ruby/internal/value.h ifaddr.o: $(hdrdir)/ruby/internal/value_type.h @@ -761,27 +819,46 @@ ifaddr.o: $(hdrdir)/ruby/ruby.h ifaddr.o: $(hdrdir)/ruby/st.h ifaddr.o: $(hdrdir)/ruby/subst.h ifaddr.o: $(hdrdir)/ruby/thread.h +ifaddr.o: $(hdrdir)/ruby/thread_native.h ifaddr.o: $(hdrdir)/ruby/util.h +ifaddr.o: $(hdrdir)/ruby/version.h +ifaddr.o: $(top_srcdir)/ccan/check_type/check_type.h +ifaddr.o: $(top_srcdir)/ccan/container_of/container_of.h +ifaddr.o: $(top_srcdir)/ccan/list/list.h +ifaddr.o: $(top_srcdir)/ccan/str/str.h ifaddr.o: $(top_srcdir)/internal.h ifaddr.o: $(top_srcdir)/internal/array.h +ifaddr.o: $(top_srcdir)/internal/basic_operators.h ifaddr.o: $(top_srcdir)/internal/compilers.h ifaddr.o: $(top_srcdir)/internal/error.h ifaddr.o: $(top_srcdir)/internal/gc.h +ifaddr.o: $(top_srcdir)/internal/imemo.h ifaddr.o: $(top_srcdir)/internal/io.h +ifaddr.o: $(top_srcdir)/internal/sanitizers.h ifaddr.o: $(top_srcdir)/internal/serial.h ifaddr.o: $(top_srcdir)/internal/static_assert.h ifaddr.o: $(top_srcdir)/internal/string.h ifaddr.o: $(top_srcdir)/internal/thread.h ifaddr.o: $(top_srcdir)/internal/vm.h ifaddr.o: $(top_srcdir)/internal/warnings.h +ifaddr.o: $(top_srcdir)/method.h +ifaddr.o: $(top_srcdir)/node.h +ifaddr.o: $(top_srcdir)/ruby_assert.h +ifaddr.o: $(top_srcdir)/ruby_atomic.h +ifaddr.o: $(top_srcdir)/rubyparser.h ifaddr.o: $(top_srcdir)/shape.h +ifaddr.o: $(top_srcdir)/thread_pthread.h +ifaddr.o: $(top_srcdir)/vm_core.h +ifaddr.o: $(top_srcdir)/vm_opts.h ifaddr.o: constdefs.h ifaddr.o: ifaddr.c ifaddr.o: rubysocket.h ifaddr.o: sockport.h +ifaddr.o: {$(VPATH)}id.h init.o: $(RUBY_EXTCONF_H) init.o: $(arch_hdrdir)/ruby/config.h init.o: $(hdrdir)/ruby/assert.h +init.o: $(hdrdir)/ruby/atomic.h init.o: $(hdrdir)/ruby/backward.h init.o: $(hdrdir)/ruby/backward/2/assume.h init.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -834,6 +911,7 @@ init.o: $(hdrdir)/ruby/internal/attr/noexcept.h init.o: $(hdrdir)/ruby/internal/attr/noinline.h init.o: $(hdrdir)/ruby/internal/attr/nonnull.h init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h init.o: $(hdrdir)/ruby/internal/attr/pure.h init.o: $(hdrdir)/ruby/internal/attr/restrict.h init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -902,7 +980,6 @@ init.o: $(hdrdir)/ruby/internal/intern/enumerator.h init.o: $(hdrdir)/ruby/internal/intern/error.h init.o: $(hdrdir)/ruby/internal/intern/eval.h init.o: $(hdrdir)/ruby/internal/intern/file.h -init.o: $(hdrdir)/ruby/internal/intern/gc.h init.o: $(hdrdir)/ruby/internal/intern/hash.h init.o: $(hdrdir)/ruby/internal/intern/io.h init.o: $(hdrdir)/ruby/internal/intern/load.h @@ -933,12 +1010,12 @@ init.o: $(hdrdir)/ruby/internal/memory.h init.o: $(hdrdir)/ruby/internal/method.h init.o: $(hdrdir)/ruby/internal/module.h init.o: $(hdrdir)/ruby/internal/newobj.h -init.o: $(hdrdir)/ruby/internal/rgengc.h init.o: $(hdrdir)/ruby/internal/scan_args.h init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -953,27 +1030,46 @@ init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h init.o: $(hdrdir)/ruby/thread.h +init.o: $(hdrdir)/ruby/thread_native.h init.o: $(hdrdir)/ruby/util.h +init.o: $(hdrdir)/ruby/version.h +init.o: $(top_srcdir)/ccan/check_type/check_type.h +init.o: $(top_srcdir)/ccan/container_of/container_of.h +init.o: $(top_srcdir)/ccan/list/list.h +init.o: $(top_srcdir)/ccan/str/str.h init.o: $(top_srcdir)/internal.h init.o: $(top_srcdir)/internal/array.h +init.o: $(top_srcdir)/internal/basic_operators.h init.o: $(top_srcdir)/internal/compilers.h init.o: $(top_srcdir)/internal/error.h init.o: $(top_srcdir)/internal/gc.h +init.o: $(top_srcdir)/internal/imemo.h init.o: $(top_srcdir)/internal/io.h +init.o: $(top_srcdir)/internal/sanitizers.h init.o: $(top_srcdir)/internal/serial.h init.o: $(top_srcdir)/internal/static_assert.h init.o: $(top_srcdir)/internal/string.h init.o: $(top_srcdir)/internal/thread.h init.o: $(top_srcdir)/internal/vm.h init.o: $(top_srcdir)/internal/warnings.h +init.o: $(top_srcdir)/method.h +init.o: $(top_srcdir)/node.h +init.o: $(top_srcdir)/ruby_assert.h +init.o: $(top_srcdir)/ruby_atomic.h +init.o: $(top_srcdir)/rubyparser.h init.o: $(top_srcdir)/shape.h +init.o: $(top_srcdir)/thread_pthread.h +init.o: $(top_srcdir)/vm_core.h +init.o: $(top_srcdir)/vm_opts.h init.o: constdefs.h init.o: init.c init.o: rubysocket.h init.o: sockport.h +init.o: {$(VPATH)}id.h ipsocket.o: $(RUBY_EXTCONF_H) ipsocket.o: $(arch_hdrdir)/ruby/config.h ipsocket.o: $(hdrdir)/ruby/assert.h +ipsocket.o: $(hdrdir)/ruby/atomic.h ipsocket.o: $(hdrdir)/ruby/backward.h ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h ipsocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1026,6 +1122,7 @@ ipsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h ipsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h ipsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h ipsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h ipsocket.o: $(hdrdir)/ruby/internal/attr/pure.h ipsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h ipsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1094,7 +1191,6 @@ ipsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h ipsocket.o: $(hdrdir)/ruby/internal/intern/error.h ipsocket.o: $(hdrdir)/ruby/internal/intern/eval.h ipsocket.o: $(hdrdir)/ruby/internal/intern/file.h -ipsocket.o: $(hdrdir)/ruby/internal/intern/gc.h ipsocket.o: $(hdrdir)/ruby/internal/intern/hash.h ipsocket.o: $(hdrdir)/ruby/internal/intern/io.h ipsocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1125,12 +1221,12 @@ ipsocket.o: $(hdrdir)/ruby/internal/memory.h ipsocket.o: $(hdrdir)/ruby/internal/method.h ipsocket.o: $(hdrdir)/ruby/internal/module.h ipsocket.o: $(hdrdir)/ruby/internal/newobj.h -ipsocket.o: $(hdrdir)/ruby/internal/rgengc.h ipsocket.o: $(hdrdir)/ruby/internal/scan_args.h ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h +ipsocket.o: $(hdrdir)/ruby/internal/stdckdint.h ipsocket.o: $(hdrdir)/ruby/internal/symbol.h ipsocket.o: $(hdrdir)/ruby/internal/value.h ipsocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -1145,27 +1241,46 @@ ipsocket.o: $(hdrdir)/ruby/ruby.h ipsocket.o: $(hdrdir)/ruby/st.h ipsocket.o: $(hdrdir)/ruby/subst.h ipsocket.o: $(hdrdir)/ruby/thread.h +ipsocket.o: $(hdrdir)/ruby/thread_native.h ipsocket.o: $(hdrdir)/ruby/util.h +ipsocket.o: $(hdrdir)/ruby/version.h +ipsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +ipsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +ipsocket.o: $(top_srcdir)/ccan/list/list.h +ipsocket.o: $(top_srcdir)/ccan/str/str.h ipsocket.o: $(top_srcdir)/internal.h ipsocket.o: $(top_srcdir)/internal/array.h +ipsocket.o: $(top_srcdir)/internal/basic_operators.h ipsocket.o: $(top_srcdir)/internal/compilers.h ipsocket.o: $(top_srcdir)/internal/error.h ipsocket.o: $(top_srcdir)/internal/gc.h +ipsocket.o: $(top_srcdir)/internal/imemo.h ipsocket.o: $(top_srcdir)/internal/io.h +ipsocket.o: $(top_srcdir)/internal/sanitizers.h ipsocket.o: $(top_srcdir)/internal/serial.h ipsocket.o: $(top_srcdir)/internal/static_assert.h ipsocket.o: $(top_srcdir)/internal/string.h ipsocket.o: $(top_srcdir)/internal/thread.h ipsocket.o: $(top_srcdir)/internal/vm.h ipsocket.o: $(top_srcdir)/internal/warnings.h +ipsocket.o: $(top_srcdir)/method.h +ipsocket.o: $(top_srcdir)/node.h +ipsocket.o: $(top_srcdir)/ruby_assert.h +ipsocket.o: $(top_srcdir)/ruby_atomic.h +ipsocket.o: $(top_srcdir)/rubyparser.h ipsocket.o: $(top_srcdir)/shape.h +ipsocket.o: $(top_srcdir)/thread_pthread.h +ipsocket.o: $(top_srcdir)/vm_core.h +ipsocket.o: $(top_srcdir)/vm_opts.h ipsocket.o: constdefs.h ipsocket.o: ipsocket.c ipsocket.o: rubysocket.h ipsocket.o: sockport.h +ipsocket.o: {$(VPATH)}id.h option.o: $(RUBY_EXTCONF_H) option.o: $(arch_hdrdir)/ruby/config.h option.o: $(hdrdir)/ruby/assert.h +option.o: $(hdrdir)/ruby/atomic.h option.o: $(hdrdir)/ruby/backward.h option.o: $(hdrdir)/ruby/backward/2/assume.h option.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1218,6 +1333,7 @@ option.o: $(hdrdir)/ruby/internal/attr/noexcept.h option.o: $(hdrdir)/ruby/internal/attr/noinline.h option.o: $(hdrdir)/ruby/internal/attr/nonnull.h option.o: $(hdrdir)/ruby/internal/attr/noreturn.h +option.o: $(hdrdir)/ruby/internal/attr/packed_struct.h option.o: $(hdrdir)/ruby/internal/attr/pure.h option.o: $(hdrdir)/ruby/internal/attr/restrict.h option.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1286,7 +1402,6 @@ option.o: $(hdrdir)/ruby/internal/intern/enumerator.h option.o: $(hdrdir)/ruby/internal/intern/error.h option.o: $(hdrdir)/ruby/internal/intern/eval.h option.o: $(hdrdir)/ruby/internal/intern/file.h -option.o: $(hdrdir)/ruby/internal/intern/gc.h option.o: $(hdrdir)/ruby/internal/intern/hash.h option.o: $(hdrdir)/ruby/internal/intern/io.h option.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1317,12 +1432,12 @@ option.o: $(hdrdir)/ruby/internal/memory.h option.o: $(hdrdir)/ruby/internal/method.h option.o: $(hdrdir)/ruby/internal/module.h option.o: $(hdrdir)/ruby/internal/newobj.h -option.o: $(hdrdir)/ruby/internal/rgengc.h option.o: $(hdrdir)/ruby/internal/scan_args.h option.o: $(hdrdir)/ruby/internal/special_consts.h option.o: $(hdrdir)/ruby/internal/static_assert.h option.o: $(hdrdir)/ruby/internal/stdalign.h option.o: $(hdrdir)/ruby/internal/stdbool.h +option.o: $(hdrdir)/ruby/internal/stdckdint.h option.o: $(hdrdir)/ruby/internal/symbol.h option.o: $(hdrdir)/ruby/internal/value.h option.o: $(hdrdir)/ruby/internal/value_type.h @@ -1337,27 +1452,46 @@ option.o: $(hdrdir)/ruby/ruby.h option.o: $(hdrdir)/ruby/st.h option.o: $(hdrdir)/ruby/subst.h option.o: $(hdrdir)/ruby/thread.h +option.o: $(hdrdir)/ruby/thread_native.h option.o: $(hdrdir)/ruby/util.h +option.o: $(hdrdir)/ruby/version.h +option.o: $(top_srcdir)/ccan/check_type/check_type.h +option.o: $(top_srcdir)/ccan/container_of/container_of.h +option.o: $(top_srcdir)/ccan/list/list.h +option.o: $(top_srcdir)/ccan/str/str.h option.o: $(top_srcdir)/internal.h option.o: $(top_srcdir)/internal/array.h +option.o: $(top_srcdir)/internal/basic_operators.h option.o: $(top_srcdir)/internal/compilers.h option.o: $(top_srcdir)/internal/error.h option.o: $(top_srcdir)/internal/gc.h +option.o: $(top_srcdir)/internal/imemo.h option.o: $(top_srcdir)/internal/io.h +option.o: $(top_srcdir)/internal/sanitizers.h option.o: $(top_srcdir)/internal/serial.h option.o: $(top_srcdir)/internal/static_assert.h option.o: $(top_srcdir)/internal/string.h option.o: $(top_srcdir)/internal/thread.h option.o: $(top_srcdir)/internal/vm.h option.o: $(top_srcdir)/internal/warnings.h +option.o: $(top_srcdir)/method.h +option.o: $(top_srcdir)/node.h +option.o: $(top_srcdir)/ruby_assert.h +option.o: $(top_srcdir)/ruby_atomic.h +option.o: $(top_srcdir)/rubyparser.h option.o: $(top_srcdir)/shape.h +option.o: $(top_srcdir)/thread_pthread.h +option.o: $(top_srcdir)/vm_core.h +option.o: $(top_srcdir)/vm_opts.h option.o: constdefs.h option.o: option.c option.o: rubysocket.h option.o: sockport.h +option.o: {$(VPATH)}id.h raddrinfo.o: $(RUBY_EXTCONF_H) raddrinfo.o: $(arch_hdrdir)/ruby/config.h raddrinfo.o: $(hdrdir)/ruby/assert.h +raddrinfo.o: $(hdrdir)/ruby/atomic.h raddrinfo.o: $(hdrdir)/ruby/backward.h raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h raddrinfo.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1410,6 +1544,7 @@ raddrinfo.o: $(hdrdir)/ruby/internal/attr/noexcept.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/noinline.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/nonnull.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/noreturn.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/packed_struct.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/pure.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/restrict.h raddrinfo.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1478,7 +1613,6 @@ raddrinfo.o: $(hdrdir)/ruby/internal/intern/enumerator.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/error.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/eval.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/file.h -raddrinfo.o: $(hdrdir)/ruby/internal/intern/gc.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/hash.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/io.h raddrinfo.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1509,12 +1643,12 @@ raddrinfo.o: $(hdrdir)/ruby/internal/memory.h raddrinfo.o: $(hdrdir)/ruby/internal/method.h raddrinfo.o: $(hdrdir)/ruby/internal/module.h raddrinfo.o: $(hdrdir)/ruby/internal/newobj.h -raddrinfo.o: $(hdrdir)/ruby/internal/rgengc.h raddrinfo.o: $(hdrdir)/ruby/internal/scan_args.h raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdckdint.h raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h raddrinfo.o: $(hdrdir)/ruby/internal/value.h raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h @@ -1529,27 +1663,46 @@ raddrinfo.o: $(hdrdir)/ruby/ruby.h raddrinfo.o: $(hdrdir)/ruby/st.h raddrinfo.o: $(hdrdir)/ruby/subst.h raddrinfo.o: $(hdrdir)/ruby/thread.h +raddrinfo.o: $(hdrdir)/ruby/thread_native.h raddrinfo.o: $(hdrdir)/ruby/util.h +raddrinfo.o: $(hdrdir)/ruby/version.h +raddrinfo.o: $(top_srcdir)/ccan/check_type/check_type.h +raddrinfo.o: $(top_srcdir)/ccan/container_of/container_of.h +raddrinfo.o: $(top_srcdir)/ccan/list/list.h +raddrinfo.o: $(top_srcdir)/ccan/str/str.h raddrinfo.o: $(top_srcdir)/internal.h raddrinfo.o: $(top_srcdir)/internal/array.h +raddrinfo.o: $(top_srcdir)/internal/basic_operators.h raddrinfo.o: $(top_srcdir)/internal/compilers.h raddrinfo.o: $(top_srcdir)/internal/error.h raddrinfo.o: $(top_srcdir)/internal/gc.h +raddrinfo.o: $(top_srcdir)/internal/imemo.h raddrinfo.o: $(top_srcdir)/internal/io.h +raddrinfo.o: $(top_srcdir)/internal/sanitizers.h raddrinfo.o: $(top_srcdir)/internal/serial.h raddrinfo.o: $(top_srcdir)/internal/static_assert.h raddrinfo.o: $(top_srcdir)/internal/string.h raddrinfo.o: $(top_srcdir)/internal/thread.h raddrinfo.o: $(top_srcdir)/internal/vm.h raddrinfo.o: $(top_srcdir)/internal/warnings.h +raddrinfo.o: $(top_srcdir)/method.h +raddrinfo.o: $(top_srcdir)/node.h +raddrinfo.o: $(top_srcdir)/ruby_assert.h +raddrinfo.o: $(top_srcdir)/ruby_atomic.h +raddrinfo.o: $(top_srcdir)/rubyparser.h raddrinfo.o: $(top_srcdir)/shape.h +raddrinfo.o: $(top_srcdir)/thread_pthread.h +raddrinfo.o: $(top_srcdir)/vm_core.h +raddrinfo.o: $(top_srcdir)/vm_opts.h raddrinfo.o: constdefs.h raddrinfo.o: raddrinfo.c raddrinfo.o: rubysocket.h raddrinfo.o: sockport.h +raddrinfo.o: {$(VPATH)}id.h socket.o: $(RUBY_EXTCONF_H) socket.o: $(arch_hdrdir)/ruby/config.h socket.o: $(hdrdir)/ruby/assert.h +socket.o: $(hdrdir)/ruby/atomic.h socket.o: $(hdrdir)/ruby/backward.h socket.o: $(hdrdir)/ruby/backward/2/assume.h socket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1602,6 +1755,7 @@ socket.o: $(hdrdir)/ruby/internal/attr/noexcept.h socket.o: $(hdrdir)/ruby/internal/attr/noinline.h socket.o: $(hdrdir)/ruby/internal/attr/nonnull.h socket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +socket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h socket.o: $(hdrdir)/ruby/internal/attr/pure.h socket.o: $(hdrdir)/ruby/internal/attr/restrict.h socket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1670,7 +1824,6 @@ socket.o: $(hdrdir)/ruby/internal/intern/enumerator.h socket.o: $(hdrdir)/ruby/internal/intern/error.h socket.o: $(hdrdir)/ruby/internal/intern/eval.h socket.o: $(hdrdir)/ruby/internal/intern/file.h -socket.o: $(hdrdir)/ruby/internal/intern/gc.h socket.o: $(hdrdir)/ruby/internal/intern/hash.h socket.o: $(hdrdir)/ruby/internal/intern/io.h socket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1701,12 +1854,12 @@ socket.o: $(hdrdir)/ruby/internal/memory.h socket.o: $(hdrdir)/ruby/internal/method.h socket.o: $(hdrdir)/ruby/internal/module.h socket.o: $(hdrdir)/ruby/internal/newobj.h -socket.o: $(hdrdir)/ruby/internal/rgengc.h socket.o: $(hdrdir)/ruby/internal/scan_args.h socket.o: $(hdrdir)/ruby/internal/special_consts.h socket.o: $(hdrdir)/ruby/internal/static_assert.h socket.o: $(hdrdir)/ruby/internal/stdalign.h socket.o: $(hdrdir)/ruby/internal/stdbool.h +socket.o: $(hdrdir)/ruby/internal/stdckdint.h socket.o: $(hdrdir)/ruby/internal/symbol.h socket.o: $(hdrdir)/ruby/internal/value.h socket.o: $(hdrdir)/ruby/internal/value_type.h @@ -1721,27 +1874,46 @@ socket.o: $(hdrdir)/ruby/ruby.h socket.o: $(hdrdir)/ruby/st.h socket.o: $(hdrdir)/ruby/subst.h socket.o: $(hdrdir)/ruby/thread.h +socket.o: $(hdrdir)/ruby/thread_native.h socket.o: $(hdrdir)/ruby/util.h +socket.o: $(hdrdir)/ruby/version.h +socket.o: $(top_srcdir)/ccan/check_type/check_type.h +socket.o: $(top_srcdir)/ccan/container_of/container_of.h +socket.o: $(top_srcdir)/ccan/list/list.h +socket.o: $(top_srcdir)/ccan/str/str.h socket.o: $(top_srcdir)/internal.h socket.o: $(top_srcdir)/internal/array.h +socket.o: $(top_srcdir)/internal/basic_operators.h socket.o: $(top_srcdir)/internal/compilers.h socket.o: $(top_srcdir)/internal/error.h socket.o: $(top_srcdir)/internal/gc.h +socket.o: $(top_srcdir)/internal/imemo.h socket.o: $(top_srcdir)/internal/io.h +socket.o: $(top_srcdir)/internal/sanitizers.h socket.o: $(top_srcdir)/internal/serial.h socket.o: $(top_srcdir)/internal/static_assert.h socket.o: $(top_srcdir)/internal/string.h socket.o: $(top_srcdir)/internal/thread.h socket.o: $(top_srcdir)/internal/vm.h socket.o: $(top_srcdir)/internal/warnings.h +socket.o: $(top_srcdir)/method.h +socket.o: $(top_srcdir)/node.h +socket.o: $(top_srcdir)/ruby_assert.h +socket.o: $(top_srcdir)/ruby_atomic.h +socket.o: $(top_srcdir)/rubyparser.h socket.o: $(top_srcdir)/shape.h +socket.o: $(top_srcdir)/thread_pthread.h +socket.o: $(top_srcdir)/vm_core.h +socket.o: $(top_srcdir)/vm_opts.h socket.o: constdefs.h socket.o: rubysocket.h socket.o: socket.c socket.o: sockport.h +socket.o: {$(VPATH)}id.h sockssocket.o: $(RUBY_EXTCONF_H) sockssocket.o: $(arch_hdrdir)/ruby/config.h sockssocket.o: $(hdrdir)/ruby/assert.h +sockssocket.o: $(hdrdir)/ruby/atomic.h sockssocket.o: $(hdrdir)/ruby/backward.h sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h sockssocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1794,6 +1966,7 @@ sockssocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h sockssocket.o: $(hdrdir)/ruby/internal/attr/noinline.h sockssocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h sockssocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h sockssocket.o: $(hdrdir)/ruby/internal/attr/pure.h sockssocket.o: $(hdrdir)/ruby/internal/attr/restrict.h sockssocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1862,7 +2035,6 @@ sockssocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h sockssocket.o: $(hdrdir)/ruby/internal/intern/error.h sockssocket.o: $(hdrdir)/ruby/internal/intern/eval.h sockssocket.o: $(hdrdir)/ruby/internal/intern/file.h -sockssocket.o: $(hdrdir)/ruby/internal/intern/gc.h sockssocket.o: $(hdrdir)/ruby/internal/intern/hash.h sockssocket.o: $(hdrdir)/ruby/internal/intern/io.h sockssocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1893,12 +2065,12 @@ sockssocket.o: $(hdrdir)/ruby/internal/memory.h sockssocket.o: $(hdrdir)/ruby/internal/method.h sockssocket.o: $(hdrdir)/ruby/internal/module.h sockssocket.o: $(hdrdir)/ruby/internal/newobj.h -sockssocket.o: $(hdrdir)/ruby/internal/rgengc.h sockssocket.o: $(hdrdir)/ruby/internal/scan_args.h sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h +sockssocket.o: $(hdrdir)/ruby/internal/stdckdint.h sockssocket.o: $(hdrdir)/ruby/internal/symbol.h sockssocket.o: $(hdrdir)/ruby/internal/value.h sockssocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -1913,27 +2085,46 @@ sockssocket.o: $(hdrdir)/ruby/ruby.h sockssocket.o: $(hdrdir)/ruby/st.h sockssocket.o: $(hdrdir)/ruby/subst.h sockssocket.o: $(hdrdir)/ruby/thread.h +sockssocket.o: $(hdrdir)/ruby/thread_native.h sockssocket.o: $(hdrdir)/ruby/util.h +sockssocket.o: $(hdrdir)/ruby/version.h +sockssocket.o: $(top_srcdir)/ccan/check_type/check_type.h +sockssocket.o: $(top_srcdir)/ccan/container_of/container_of.h +sockssocket.o: $(top_srcdir)/ccan/list/list.h +sockssocket.o: $(top_srcdir)/ccan/str/str.h sockssocket.o: $(top_srcdir)/internal.h sockssocket.o: $(top_srcdir)/internal/array.h +sockssocket.o: $(top_srcdir)/internal/basic_operators.h sockssocket.o: $(top_srcdir)/internal/compilers.h sockssocket.o: $(top_srcdir)/internal/error.h sockssocket.o: $(top_srcdir)/internal/gc.h +sockssocket.o: $(top_srcdir)/internal/imemo.h sockssocket.o: $(top_srcdir)/internal/io.h +sockssocket.o: $(top_srcdir)/internal/sanitizers.h sockssocket.o: $(top_srcdir)/internal/serial.h sockssocket.o: $(top_srcdir)/internal/static_assert.h sockssocket.o: $(top_srcdir)/internal/string.h sockssocket.o: $(top_srcdir)/internal/thread.h sockssocket.o: $(top_srcdir)/internal/vm.h sockssocket.o: $(top_srcdir)/internal/warnings.h +sockssocket.o: $(top_srcdir)/method.h +sockssocket.o: $(top_srcdir)/node.h +sockssocket.o: $(top_srcdir)/ruby_assert.h +sockssocket.o: $(top_srcdir)/ruby_atomic.h +sockssocket.o: $(top_srcdir)/rubyparser.h sockssocket.o: $(top_srcdir)/shape.h +sockssocket.o: $(top_srcdir)/thread_pthread.h +sockssocket.o: $(top_srcdir)/vm_core.h +sockssocket.o: $(top_srcdir)/vm_opts.h sockssocket.o: constdefs.h sockssocket.o: rubysocket.h sockssocket.o: sockport.h sockssocket.o: sockssocket.c +sockssocket.o: {$(VPATH)}id.h tcpserver.o: $(RUBY_EXTCONF_H) tcpserver.o: $(arch_hdrdir)/ruby/config.h tcpserver.o: $(hdrdir)/ruby/assert.h +tcpserver.o: $(hdrdir)/ruby/atomic.h tcpserver.o: $(hdrdir)/ruby/backward.h tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h tcpserver.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -1986,6 +2177,7 @@ tcpserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h tcpserver.o: $(hdrdir)/ruby/internal/attr/noinline.h tcpserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h tcpserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h tcpserver.o: $(hdrdir)/ruby/internal/attr/pure.h tcpserver.o: $(hdrdir)/ruby/internal/attr/restrict.h tcpserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -2054,7 +2246,6 @@ tcpserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h tcpserver.o: $(hdrdir)/ruby/internal/intern/error.h tcpserver.o: $(hdrdir)/ruby/internal/intern/eval.h tcpserver.o: $(hdrdir)/ruby/internal/intern/file.h -tcpserver.o: $(hdrdir)/ruby/internal/intern/gc.h tcpserver.o: $(hdrdir)/ruby/internal/intern/hash.h tcpserver.o: $(hdrdir)/ruby/internal/intern/io.h tcpserver.o: $(hdrdir)/ruby/internal/intern/load.h @@ -2085,12 +2276,12 @@ tcpserver.o: $(hdrdir)/ruby/internal/memory.h tcpserver.o: $(hdrdir)/ruby/internal/method.h tcpserver.o: $(hdrdir)/ruby/internal/module.h tcpserver.o: $(hdrdir)/ruby/internal/newobj.h -tcpserver.o: $(hdrdir)/ruby/internal/rgengc.h tcpserver.o: $(hdrdir)/ruby/internal/scan_args.h tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h +tcpserver.o: $(hdrdir)/ruby/internal/stdckdint.h tcpserver.o: $(hdrdir)/ruby/internal/symbol.h tcpserver.o: $(hdrdir)/ruby/internal/value.h tcpserver.o: $(hdrdir)/ruby/internal/value_type.h @@ -2105,27 +2296,46 @@ tcpserver.o: $(hdrdir)/ruby/ruby.h tcpserver.o: $(hdrdir)/ruby/st.h tcpserver.o: $(hdrdir)/ruby/subst.h tcpserver.o: $(hdrdir)/ruby/thread.h +tcpserver.o: $(hdrdir)/ruby/thread_native.h tcpserver.o: $(hdrdir)/ruby/util.h +tcpserver.o: $(hdrdir)/ruby/version.h +tcpserver.o: $(top_srcdir)/ccan/check_type/check_type.h +tcpserver.o: $(top_srcdir)/ccan/container_of/container_of.h +tcpserver.o: $(top_srcdir)/ccan/list/list.h +tcpserver.o: $(top_srcdir)/ccan/str/str.h tcpserver.o: $(top_srcdir)/internal.h tcpserver.o: $(top_srcdir)/internal/array.h +tcpserver.o: $(top_srcdir)/internal/basic_operators.h tcpserver.o: $(top_srcdir)/internal/compilers.h tcpserver.o: $(top_srcdir)/internal/error.h tcpserver.o: $(top_srcdir)/internal/gc.h +tcpserver.o: $(top_srcdir)/internal/imemo.h tcpserver.o: $(top_srcdir)/internal/io.h +tcpserver.o: $(top_srcdir)/internal/sanitizers.h tcpserver.o: $(top_srcdir)/internal/serial.h tcpserver.o: $(top_srcdir)/internal/static_assert.h tcpserver.o: $(top_srcdir)/internal/string.h tcpserver.o: $(top_srcdir)/internal/thread.h tcpserver.o: $(top_srcdir)/internal/vm.h tcpserver.o: $(top_srcdir)/internal/warnings.h +tcpserver.o: $(top_srcdir)/method.h +tcpserver.o: $(top_srcdir)/node.h +tcpserver.o: $(top_srcdir)/ruby_assert.h +tcpserver.o: $(top_srcdir)/ruby_atomic.h +tcpserver.o: $(top_srcdir)/rubyparser.h tcpserver.o: $(top_srcdir)/shape.h +tcpserver.o: $(top_srcdir)/thread_pthread.h +tcpserver.o: $(top_srcdir)/vm_core.h +tcpserver.o: $(top_srcdir)/vm_opts.h tcpserver.o: constdefs.h tcpserver.o: rubysocket.h tcpserver.o: sockport.h tcpserver.o: tcpserver.c +tcpserver.o: {$(VPATH)}id.h tcpsocket.o: $(RUBY_EXTCONF_H) tcpsocket.o: $(arch_hdrdir)/ruby/config.h tcpsocket.o: $(hdrdir)/ruby/assert.h +tcpsocket.o: $(hdrdir)/ruby/atomic.h tcpsocket.o: $(hdrdir)/ruby/backward.h tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h tcpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -2178,6 +2388,7 @@ tcpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h tcpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -2246,7 +2457,6 @@ tcpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/error.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/file.h -tcpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/io.h tcpsocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -2277,12 +2487,12 @@ tcpsocket.o: $(hdrdir)/ruby/internal/memory.h tcpsocket.o: $(hdrdir)/ruby/internal/method.h tcpsocket.o: $(hdrdir)/ruby/internal/module.h tcpsocket.o: $(hdrdir)/ruby/internal/newobj.h -tcpsocket.o: $(hdrdir)/ruby/internal/rgengc.h tcpsocket.o: $(hdrdir)/ruby/internal/scan_args.h tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h tcpsocket.o: $(hdrdir)/ruby/internal/value.h tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -2297,27 +2507,46 @@ tcpsocket.o: $(hdrdir)/ruby/ruby.h tcpsocket.o: $(hdrdir)/ruby/st.h tcpsocket.o: $(hdrdir)/ruby/subst.h tcpsocket.o: $(hdrdir)/ruby/thread.h +tcpsocket.o: $(hdrdir)/ruby/thread_native.h tcpsocket.o: $(hdrdir)/ruby/util.h +tcpsocket.o: $(hdrdir)/ruby/version.h +tcpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +tcpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +tcpsocket.o: $(top_srcdir)/ccan/list/list.h +tcpsocket.o: $(top_srcdir)/ccan/str/str.h tcpsocket.o: $(top_srcdir)/internal.h tcpsocket.o: $(top_srcdir)/internal/array.h +tcpsocket.o: $(top_srcdir)/internal/basic_operators.h tcpsocket.o: $(top_srcdir)/internal/compilers.h tcpsocket.o: $(top_srcdir)/internal/error.h tcpsocket.o: $(top_srcdir)/internal/gc.h +tcpsocket.o: $(top_srcdir)/internal/imemo.h tcpsocket.o: $(top_srcdir)/internal/io.h +tcpsocket.o: $(top_srcdir)/internal/sanitizers.h tcpsocket.o: $(top_srcdir)/internal/serial.h tcpsocket.o: $(top_srcdir)/internal/static_assert.h tcpsocket.o: $(top_srcdir)/internal/string.h tcpsocket.o: $(top_srcdir)/internal/thread.h tcpsocket.o: $(top_srcdir)/internal/vm.h tcpsocket.o: $(top_srcdir)/internal/warnings.h +tcpsocket.o: $(top_srcdir)/method.h +tcpsocket.o: $(top_srcdir)/node.h +tcpsocket.o: $(top_srcdir)/ruby_assert.h +tcpsocket.o: $(top_srcdir)/ruby_atomic.h +tcpsocket.o: $(top_srcdir)/rubyparser.h tcpsocket.o: $(top_srcdir)/shape.h +tcpsocket.o: $(top_srcdir)/thread_pthread.h +tcpsocket.o: $(top_srcdir)/vm_core.h +tcpsocket.o: $(top_srcdir)/vm_opts.h tcpsocket.o: constdefs.h tcpsocket.o: rubysocket.h tcpsocket.o: sockport.h tcpsocket.o: tcpsocket.c +tcpsocket.o: {$(VPATH)}id.h udpsocket.o: $(RUBY_EXTCONF_H) udpsocket.o: $(arch_hdrdir)/ruby/config.h udpsocket.o: $(hdrdir)/ruby/assert.h +udpsocket.o: $(hdrdir)/ruby/atomic.h udpsocket.o: $(hdrdir)/ruby/backward.h udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h udpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -2370,6 +2599,7 @@ udpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h udpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h udpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h udpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h udpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h udpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h udpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -2438,7 +2668,6 @@ udpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h udpsocket.o: $(hdrdir)/ruby/internal/intern/error.h udpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h udpsocket.o: $(hdrdir)/ruby/internal/intern/file.h -udpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h udpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h udpsocket.o: $(hdrdir)/ruby/internal/intern/io.h udpsocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -2469,12 +2698,12 @@ udpsocket.o: $(hdrdir)/ruby/internal/memory.h udpsocket.o: $(hdrdir)/ruby/internal/method.h udpsocket.o: $(hdrdir)/ruby/internal/module.h udpsocket.o: $(hdrdir)/ruby/internal/newobj.h -udpsocket.o: $(hdrdir)/ruby/internal/rgengc.h udpsocket.o: $(hdrdir)/ruby/internal/scan_args.h udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +udpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h udpsocket.o: $(hdrdir)/ruby/internal/symbol.h udpsocket.o: $(hdrdir)/ruby/internal/value.h udpsocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -2489,27 +2718,46 @@ udpsocket.o: $(hdrdir)/ruby/ruby.h udpsocket.o: $(hdrdir)/ruby/st.h udpsocket.o: $(hdrdir)/ruby/subst.h udpsocket.o: $(hdrdir)/ruby/thread.h +udpsocket.o: $(hdrdir)/ruby/thread_native.h udpsocket.o: $(hdrdir)/ruby/util.h +udpsocket.o: $(hdrdir)/ruby/version.h +udpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +udpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +udpsocket.o: $(top_srcdir)/ccan/list/list.h +udpsocket.o: $(top_srcdir)/ccan/str/str.h udpsocket.o: $(top_srcdir)/internal.h udpsocket.o: $(top_srcdir)/internal/array.h +udpsocket.o: $(top_srcdir)/internal/basic_operators.h udpsocket.o: $(top_srcdir)/internal/compilers.h udpsocket.o: $(top_srcdir)/internal/error.h udpsocket.o: $(top_srcdir)/internal/gc.h +udpsocket.o: $(top_srcdir)/internal/imemo.h udpsocket.o: $(top_srcdir)/internal/io.h +udpsocket.o: $(top_srcdir)/internal/sanitizers.h udpsocket.o: $(top_srcdir)/internal/serial.h udpsocket.o: $(top_srcdir)/internal/static_assert.h udpsocket.o: $(top_srcdir)/internal/string.h udpsocket.o: $(top_srcdir)/internal/thread.h udpsocket.o: $(top_srcdir)/internal/vm.h udpsocket.o: $(top_srcdir)/internal/warnings.h +udpsocket.o: $(top_srcdir)/method.h +udpsocket.o: $(top_srcdir)/node.h +udpsocket.o: $(top_srcdir)/ruby_assert.h +udpsocket.o: $(top_srcdir)/ruby_atomic.h +udpsocket.o: $(top_srcdir)/rubyparser.h udpsocket.o: $(top_srcdir)/shape.h +udpsocket.o: $(top_srcdir)/thread_pthread.h +udpsocket.o: $(top_srcdir)/vm_core.h +udpsocket.o: $(top_srcdir)/vm_opts.h udpsocket.o: constdefs.h udpsocket.o: rubysocket.h udpsocket.o: sockport.h udpsocket.o: udpsocket.c +udpsocket.o: {$(VPATH)}id.h unixserver.o: $(RUBY_EXTCONF_H) unixserver.o: $(arch_hdrdir)/ruby/config.h unixserver.o: $(hdrdir)/ruby/assert.h +unixserver.o: $(hdrdir)/ruby/atomic.h unixserver.o: $(hdrdir)/ruby/backward.h unixserver.o: $(hdrdir)/ruby/backward/2/assume.h unixserver.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -2562,6 +2810,7 @@ unixserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h unixserver.o: $(hdrdir)/ruby/internal/attr/noinline.h unixserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h unixserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h unixserver.o: $(hdrdir)/ruby/internal/attr/pure.h unixserver.o: $(hdrdir)/ruby/internal/attr/restrict.h unixserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -2630,7 +2879,6 @@ unixserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h unixserver.o: $(hdrdir)/ruby/internal/intern/error.h unixserver.o: $(hdrdir)/ruby/internal/intern/eval.h unixserver.o: $(hdrdir)/ruby/internal/intern/file.h -unixserver.o: $(hdrdir)/ruby/internal/intern/gc.h unixserver.o: $(hdrdir)/ruby/internal/intern/hash.h unixserver.o: $(hdrdir)/ruby/internal/intern/io.h unixserver.o: $(hdrdir)/ruby/internal/intern/load.h @@ -2661,12 +2909,12 @@ unixserver.o: $(hdrdir)/ruby/internal/memory.h unixserver.o: $(hdrdir)/ruby/internal/method.h unixserver.o: $(hdrdir)/ruby/internal/module.h unixserver.o: $(hdrdir)/ruby/internal/newobj.h -unixserver.o: $(hdrdir)/ruby/internal/rgengc.h unixserver.o: $(hdrdir)/ruby/internal/scan_args.h unixserver.o: $(hdrdir)/ruby/internal/special_consts.h unixserver.o: $(hdrdir)/ruby/internal/static_assert.h unixserver.o: $(hdrdir)/ruby/internal/stdalign.h unixserver.o: $(hdrdir)/ruby/internal/stdbool.h +unixserver.o: $(hdrdir)/ruby/internal/stdckdint.h unixserver.o: $(hdrdir)/ruby/internal/symbol.h unixserver.o: $(hdrdir)/ruby/internal/value.h unixserver.o: $(hdrdir)/ruby/internal/value_type.h @@ -2681,27 +2929,46 @@ unixserver.o: $(hdrdir)/ruby/ruby.h unixserver.o: $(hdrdir)/ruby/st.h unixserver.o: $(hdrdir)/ruby/subst.h unixserver.o: $(hdrdir)/ruby/thread.h +unixserver.o: $(hdrdir)/ruby/thread_native.h unixserver.o: $(hdrdir)/ruby/util.h +unixserver.o: $(hdrdir)/ruby/version.h +unixserver.o: $(top_srcdir)/ccan/check_type/check_type.h +unixserver.o: $(top_srcdir)/ccan/container_of/container_of.h +unixserver.o: $(top_srcdir)/ccan/list/list.h +unixserver.o: $(top_srcdir)/ccan/str/str.h unixserver.o: $(top_srcdir)/internal.h unixserver.o: $(top_srcdir)/internal/array.h +unixserver.o: $(top_srcdir)/internal/basic_operators.h unixserver.o: $(top_srcdir)/internal/compilers.h unixserver.o: $(top_srcdir)/internal/error.h unixserver.o: $(top_srcdir)/internal/gc.h +unixserver.o: $(top_srcdir)/internal/imemo.h unixserver.o: $(top_srcdir)/internal/io.h +unixserver.o: $(top_srcdir)/internal/sanitizers.h unixserver.o: $(top_srcdir)/internal/serial.h unixserver.o: $(top_srcdir)/internal/static_assert.h unixserver.o: $(top_srcdir)/internal/string.h unixserver.o: $(top_srcdir)/internal/thread.h unixserver.o: $(top_srcdir)/internal/vm.h unixserver.o: $(top_srcdir)/internal/warnings.h +unixserver.o: $(top_srcdir)/method.h +unixserver.o: $(top_srcdir)/node.h +unixserver.o: $(top_srcdir)/ruby_assert.h +unixserver.o: $(top_srcdir)/ruby_atomic.h +unixserver.o: $(top_srcdir)/rubyparser.h unixserver.o: $(top_srcdir)/shape.h +unixserver.o: $(top_srcdir)/thread_pthread.h +unixserver.o: $(top_srcdir)/vm_core.h +unixserver.o: $(top_srcdir)/vm_opts.h unixserver.o: constdefs.h unixserver.o: rubysocket.h unixserver.o: sockport.h unixserver.o: unixserver.c +unixserver.o: {$(VPATH)}id.h unixsocket.o: $(RUBY_EXTCONF_H) unixsocket.o: $(arch_hdrdir)/ruby/config.h unixsocket.o: $(hdrdir)/ruby/assert.h +unixsocket.o: $(hdrdir)/ruby/atomic.h unixsocket.o: $(hdrdir)/ruby/backward.h unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h unixsocket.o: $(hdrdir)/ruby/backward/2/attributes.h @@ -2754,6 +3021,7 @@ unixsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h unixsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h unixsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h unixsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h unixsocket.o: $(hdrdir)/ruby/internal/attr/pure.h unixsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h unixsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -2822,7 +3090,6 @@ unixsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h unixsocket.o: $(hdrdir)/ruby/internal/intern/error.h unixsocket.o: $(hdrdir)/ruby/internal/intern/eval.h unixsocket.o: $(hdrdir)/ruby/internal/intern/file.h -unixsocket.o: $(hdrdir)/ruby/internal/intern/gc.h unixsocket.o: $(hdrdir)/ruby/internal/intern/hash.h unixsocket.o: $(hdrdir)/ruby/internal/intern/io.h unixsocket.o: $(hdrdir)/ruby/internal/intern/load.h @@ -2853,12 +3120,12 @@ unixsocket.o: $(hdrdir)/ruby/internal/memory.h unixsocket.o: $(hdrdir)/ruby/internal/method.h unixsocket.o: $(hdrdir)/ruby/internal/module.h unixsocket.o: $(hdrdir)/ruby/internal/newobj.h -unixsocket.o: $(hdrdir)/ruby/internal/rgengc.h unixsocket.o: $(hdrdir)/ruby/internal/scan_args.h unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h +unixsocket.o: $(hdrdir)/ruby/internal/stdckdint.h unixsocket.o: $(hdrdir)/ruby/internal/symbol.h unixsocket.o: $(hdrdir)/ruby/internal/value.h unixsocket.o: $(hdrdir)/ruby/internal/value_type.h @@ -2873,22 +3140,40 @@ unixsocket.o: $(hdrdir)/ruby/ruby.h unixsocket.o: $(hdrdir)/ruby/st.h unixsocket.o: $(hdrdir)/ruby/subst.h unixsocket.o: $(hdrdir)/ruby/thread.h +unixsocket.o: $(hdrdir)/ruby/thread_native.h unixsocket.o: $(hdrdir)/ruby/util.h +unixsocket.o: $(hdrdir)/ruby/version.h +unixsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +unixsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +unixsocket.o: $(top_srcdir)/ccan/list/list.h +unixsocket.o: $(top_srcdir)/ccan/str/str.h unixsocket.o: $(top_srcdir)/internal.h unixsocket.o: $(top_srcdir)/internal/array.h +unixsocket.o: $(top_srcdir)/internal/basic_operators.h unixsocket.o: $(top_srcdir)/internal/compilers.h unixsocket.o: $(top_srcdir)/internal/error.h unixsocket.o: $(top_srcdir)/internal/gc.h +unixsocket.o: $(top_srcdir)/internal/imemo.h unixsocket.o: $(top_srcdir)/internal/io.h +unixsocket.o: $(top_srcdir)/internal/sanitizers.h unixsocket.o: $(top_srcdir)/internal/serial.h unixsocket.o: $(top_srcdir)/internal/static_assert.h unixsocket.o: $(top_srcdir)/internal/string.h unixsocket.o: $(top_srcdir)/internal/thread.h unixsocket.o: $(top_srcdir)/internal/vm.h unixsocket.o: $(top_srcdir)/internal/warnings.h +unixsocket.o: $(top_srcdir)/method.h +unixsocket.o: $(top_srcdir)/node.h +unixsocket.o: $(top_srcdir)/ruby_assert.h +unixsocket.o: $(top_srcdir)/ruby_atomic.h +unixsocket.o: $(top_srcdir)/rubyparser.h unixsocket.o: $(top_srcdir)/shape.h +unixsocket.o: $(top_srcdir)/thread_pthread.h +unixsocket.o: $(top_srcdir)/vm_core.h +unixsocket.o: $(top_srcdir)/vm_opts.h unixsocket.o: constdefs.h unixsocket.o: rubysocket.h unixsocket.o: sockport.h unixsocket.o: unixsocket.c +unixsocket.o: {$(VPATH)}id.h # AUTOGENERATED DEPENDENCIES END diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 37ff216560..d44ce31b0a 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -327,6 +327,8 @@ end net/if_dl.h arpa/nameser.h resolv.h + pthread.h + sched.h ].each {|h| if have_header(h, headers) headers << h @@ -347,10 +349,22 @@ have_type("struct sockaddr_storage", headers) have_type("struct addrinfo", headers) -if have_type("socklen_t", headers) - if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers) - $defs << "-DRSTRING_SOCKLEN=(socklen_t)RSTRING_LEN" +def check_socklen(headers) + def (fmt = "none").%(x) + x || self end + s = checking_for("RSTRING_SOCKLEN", fmt) do + if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers) + "RSTRING_LEN" + else + "RSTRING_LENINT" + end + end + $defs << "-DRSTRING_SOCKLEN=(socklen_t)"+s +end + +if have_type("socklen_t", headers) + check_socklen(headers) end have_type("struct in_pktinfo", headers) {|src| @@ -687,5 +701,10 @@ SRC "not needed" end end + + have_func("pthread_create") + have_func("pthread_detach") + + $VPATH << '$(topdir)' << '$(top_srcdir)' create_makefile("socket") end diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c index 95a2feb3be..bf0d90129f 100644 --- a/ext/socket/getaddrinfo.c +++ b/ext/socket/getaddrinfo.c @@ -219,8 +219,7 @@ freeaddrinfo(struct addrinfo *ai) do { next = ai->ai_next; - if (ai->ai_canonname) - free(ai->ai_canonname); + free(ai->ai_canonname); /* no need to free(ai->ai_addr) */ free(ai); } while ((ai = next) != NULL); diff --git a/ext/socket/init.c b/ext/socket/init.c index 557d4374a5..0e312b540e 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -27,6 +27,7 @@ VALUE rb_cSocket; VALUE rb_cAddrinfo; VALUE rb_eSocket; +VALUE rb_eResolution; #ifdef SOCKS VALUE rb_cSOCKSSocket; @@ -34,9 +35,10 @@ VALUE rb_cSOCKSSocket; int rsock_do_not_reverse_lookup = 1; static VALUE sym_wait_readable; +static ID id_error_code; void -rsock_raise_socket_error(const char *reason, int error) +rsock_raise_resolution_error(const char *reason, int error) { #ifdef EAI_SYSTEM int e; @@ -48,10 +50,14 @@ rsock_raise_socket_error(const char *reason, int error) VALUE msg = rb_sprintf("%s: ", reason); if (!enc) enc = rb_default_internal_encoding(); rb_str_concat(msg, rb_w32_conv_from_wchar(gai_strerrorW(error), enc)); - rb_exc_raise(rb_exc_new_str(rb_eSocket, msg)); #else - rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error)); + VALUE msg = rb_sprintf("%s: %s", reason, gai_strerror(error)); #endif + + StringValue(msg); + VALUE self = rb_class_new_instance(1, &msg, rb_eResolution); + rb_ivar_set(self, id_error_code, INT2NUM(error)); + rb_exc_raise(self); } #if defined __APPLE__ @@ -116,6 +122,7 @@ recvfrom_blocking(void *data) ssize_t ret; ret = recvfrom(arg->fd, RSTRING_PTR(arg->str), arg->length, arg->flags, &arg->buf.addr, &arg->alen); + if (ret != -1 && len0 < arg->alen) arg->alen = len0; @@ -147,6 +154,18 @@ recvfrom_locktmp(VALUE v) return rb_thread_io_blocking_region(recvfrom_blocking, arg, arg->fd); } +int +rsock_is_dgram(rb_io_t *fptr) +{ + int socktype; + socklen_t optlen = (socklen_t)sizeof(socktype); + int ret = getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); + if (ret == -1) { + rb_sys_fail("getsockopt(SO_TYPE)"); + } + return socktype == SOCK_DGRAM; +} + VALUE rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from) { @@ -185,8 +204,12 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from) rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); #endif - slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, (VALUE)&arg); + rb_str_locktmp(str); + slen = (long)rb_ensure(recvfrom_locktmp, (VALUE)&arg, rb_str_unlocktmp, str); + if (slen == 0 && !rsock_is_dgram(fptr)) { + return Qnil; + } if (slen >= 0) break; if (!rb_io_maybe_wait_readable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) @@ -259,6 +282,10 @@ rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, if (slen != -1 && len0 < alen) alen = len0; + if (slen == 0 && !rsock_is_dgram(fptr)) { + return Qnil; + } + if (slen < 0) { int e = errno; switch (e) { @@ -392,7 +419,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex) if (e == EWOULDBLOCK || e == EAGAIN) { if (ex == Qfalse) return sym_wait_writable; rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, - "write would block"); + "write would block"); } rb_syserr_fail_path(e, fptr->pathv); } @@ -433,9 +460,9 @@ rsock_socket(int domain, int type, int proto) fd = rsock_socket0(domain, type, proto); if (fd < 0) { - if (rb_gc_for_fd(errno)) { - fd = rsock_socket0(domain, type, proto); - } + if (rb_gc_for_fd(errno)) { + fd = rsock_socket0(domain, type, proto); + } } if (0 <= fd) rb_update_max_fd(fd); @@ -492,10 +519,10 @@ wait_connectable(int fd, struct timeval *timeout) switch (sockerr) { case 0: - /* - * be defensive in case some platforms set SO_ERROR on the original, - * interrupted connect() - */ + /* + * be defensive in case some platforms set SO_ERROR on the original, + * interrupted connect() + */ /* when the connection timed out, no errno is set and revents is 0. */ if (timeout && revents == 0) { @@ -681,9 +708,9 @@ rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len) RB_IO_POINTER(io, fptr); struct accept_arg accept_arg = { - .fd = fptr->fd, - .sockaddr = sockaddr, - .len = len + .fd = fptr->fd, + .sockaddr = sockaddr, + .len = len }; int retry = 0, peer; @@ -730,10 +757,10 @@ rsock_getfamily(rb_io_t *fptr) if (cached) { switch (cached) { #ifdef AF_UNIX - case FMODE_UNIX: return AF_UNIX; + case FMODE_UNIX: return AF_UNIX; #endif - case FMODE_INET: return AF_INET; - case FMODE_INET6: return AF_INET6; + case FMODE_INET: return AF_INET; + case FMODE_INET6: return AF_INET6; } } @@ -752,6 +779,18 @@ rsock_getfamily(rb_io_t *fptr) return ss.addr.sa_family; } +/* + * call-seq: + * error_code -> integer + * + * Returns the raw error code occurred at name resolution. + */ +static VALUE +sock_resolv_error_code(VALUE self) +{ + return rb_attr_get(self, id_error_code); +} + void rsock_init_socket_init(void) { @@ -759,6 +798,11 @@ rsock_init_socket_init(void) * SocketError is the error class for socket. */ rb_eSocket = rb_define_class("SocketError", rb_eStandardError); + /* + * ResolutionError is the error class for socket name resolution. + */ + rb_eResolution = rb_define_class_under(rb_cSocket, "ResolutionError", rb_eSocket); + rb_define_method(rb_eResolution, "error_code", sock_resolv_error_code, 0); rsock_init_ipsocket(); rsock_init_tcpsocket(); rsock_init_tcpserver(); @@ -772,6 +816,8 @@ rsock_init_socket_init(void) rsock_init_sockifaddr(); rsock_init_socket_constants(); + id_error_code = rb_intern_const("error_code"); + #undef rb_intern sym_wait_readable = ID2SYM(rb_intern("wait_readable")); diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index 6196638bd2..e953077fe6 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -1,7 +1,11 @@ # frozen_string_literal: true require 'socket.so' -require 'io/wait' + +unless IO.method_defined?(:wait_writable, false) + # It's only required on older Rubies < v3.2: + require 'io/wait' +end class Addrinfo # creates an Addrinfo object from the arguments. @@ -329,9 +333,10 @@ class BasicSocket < IO # _flags_ is zero or more of the +MSG_+ options. # The result, _mesg_, is the data received. # - # When recvfrom(2) returns 0, Socket#recv_nonblock returns - # an empty string as data. - # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but for UDP connections + # it may mean an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the number of bytes to receive from the socket @@ -476,9 +481,10 @@ class Socket < BasicSocket # The second element, _sender_addrinfo_, contains protocol-specific address # information of the sender. # - # When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns - # an empty string as data. - # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but for UDP connections + # it may mean an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the maximum number of bytes to receive from the socket @@ -593,6 +599,30 @@ class Socket < BasicSocket __accept_nonblock(exception) end + RESOLUTION_DELAY = 0.05 + private_constant :RESOLUTION_DELAY + + CONNECTION_ATTEMPT_DELAY = 0.25 + private_constant :CONNECTION_ATTEMPT_DELAY + + ADDRESS_FAMILIES = { + ipv6: Socket::AF_INET6, + ipv4: Socket::AF_INET + }.freeze + private_constant :ADDRESS_FAMILIES + + HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0 + private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED + + IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/ + private_constant :IPV6_ADRESS_FORMAT + + @tcp_fast_fallback = true + + class << self + attr_accessor :tcp_fast_fallback + end + # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) @@ -618,8 +648,491 @@ class Socket < BasicSocket # sock.close_write # puts sock.read # } - # - def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil) # :yield: socket + def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket + unless fast_fallback + return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) + end + + # Happy Eyeballs' states + # - :start + # - :v6c + # - :v4w + # - :v4c + # - :v46c + # - :v46w + # - :success + # - :failure + # - :timeout + + specified_family_name = nil + hostname_resolution_threads = [] + hostname_resolution_queue = nil + hostname_resolution_waiting = nil + hostname_resolution_expires_at = nil + selectable_addrinfos = SelectableAddrinfos.new + connecting_sockets = ConnectingSockets.new + local_addrinfos = [] + connection_attempt_delay_expires_at = nil + connection_attempt_started_at = nil + state = :start + connected_socket = nil + last_error = nil + is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) + + ret = loop do + case state + when :start + specified_family_name, next_state = host && specified_family_name_and_next_state(host) + + if local_host && local_port + specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name + local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + end + + if specified_family_name + addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + selectable_addrinfos.add(specified_family_name, addrinfos) + hostname_resolution_queue = NoHostnameResolutionQueue.new + state = next_state + next + end + + resolving_family_names = ADDRESS_FAMILIES.keys + hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size) + hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe + hostname_resolution_started_at = current_clocktime if resolv_timeout + hostname_resolution_args = [host, port, hostname_resolution_queue] + + hostname_resolution_threads.concat( + resolving_family_names.map { |family| + thread_args = [family, *hostname_resolution_args] + thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) } + Thread.pass + thread + } + ) + + hostname_resolution_retry_count = resolving_family_names.size - 1 + hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout + + while hostname_resolution_retry_count >= 0 + remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil + hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining) + + unless hostname_resolved + state = :timeout + break + end + + family_name, res = hostname_resolution_queue.get + + if res.is_a? Exception + unless (Socket.const_defined?(:EAI_ADDRFAMILY)) && + (res.is_a?(Socket::ResolutionError)) && + (res.error_code == Socket::EAI_ADDRFAMILY) + last_error = res + end + + if hostname_resolution_retry_count.zero? + state = :failure + break + end + hostname_resolution_retry_count -= 1 + else + state = case family_name + when :ipv6 then :v6c + when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w + end + selectable_addrinfos.add(family_name, res) + last_error = nil + break + end + end + + next + when :v4w + ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY) + + if ipv6_resolved + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + state = :v46c + else + state = :v4c + end + + next + when :v4c, :v6c, :v46c + connection_attempt_started_at = current_clocktime unless connection_attempt_started_at + addrinfo = selectable_addrinfos.get + + if local_addrinfos.any? + local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily } + + if local_addrinfo.nil? + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + last_error = SocketError.new 'no appropriate local address' + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + next + end + end + + connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY + + begin + result = if specified_family_name && selectable_addrinfos.empty? && + connecting_sockets.empty? && hostname_resolution_queue.closed? + local_addrinfo ? + addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) : + addrinfo.connect(timeout: connect_timeout) + else + socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) + socket.bind(local_addrinfo) if local_addrinfo + socket.connect_nonblock(addrinfo, exception: false) + end + + case result + when 0 + connected_socket = socket + state = :success + when Socket + connected_socket = result + state = :success + when :wait_writable + connecting_sockets.add(socket, addrinfo) + state = :v46w + end + rescue SystemCallError => e + last_error = e + socket.close if socket && !socket.closed? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + end + + next + when :v46w + if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero? + state = :timeout + next + end + + remaining = second_to_timeout(connection_attempt_delay_expires_at) + hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting + hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining) + + if connectable_sockets&.any? + while (connectable_socket = connectable_sockets.pop) + is_connected = + if is_windows_environment + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME) + sockopt.unpack('i').first >= 0 + else + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) + sockopt.int.zero? + end + + if is_connected + connected_socket = connectable_socket + connecting_sockets.delete connectable_socket + connectable_sockets.each do |other_connectable_socket| + other_connectable_socket.close unless other_connectable_socket.closed? + end + state = :success + break + else + failed_ai = connecting_sockets.delete connectable_socket + inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address + last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int) + connectable_socket.close unless connectable_socket.closed? + + next if connectable_sockets.any? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Wait for connection attempt delay timeout in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + end + elsif hostname_resolved&.any? + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + else + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + state = :v46c + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + + next + when :success + break connected_socket + when :failure + raise last_error + when :timeout + raise Errno::ETIMEDOUT, 'user specified timeout' + end + end + + if block_given? + begin + yield ret + ensure + ret.close + end + else + ret + end + ensure + if fast_fallback + hostname_resolution_threads.each do |thread| + thread&.exit + end + + hostname_resolution_queue&.close_all + + connecting_sockets.each do |connecting_socket| + connecting_socket.close unless connecting_socket.closed? + end + end + end + + def self.specified_family_name_and_next_state(hostname) + if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c] + elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c] + end + end + private_class_method :specified_family_name_and_next_state + + def self.hostname_resolution(family, host, port, hostname_resolution_queue) + begin + resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM) + hostname_resolution_queue.add_resolved(family, resolved_addrinfos) + rescue => e + hostname_resolution_queue.add_error(family, e) + end + end + private_class_method :hostname_resolution + + def self.second_to_timeout(ends_at) + return 0 unless ends_at + + remaining = (ends_at - current_clocktime) + remaining.negative? ? 0 : remaining + end + private_class_method :second_to_timeout + + def self.current_clocktime + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + private_class_method :current_clocktime + + class SelectableAddrinfos + PRIORITY_ON_V6 = [:ipv6, :ipv4] + PRIORITY_ON_V4 = [:ipv4, :ipv6] + + def initialize + @addrinfo_dict = {} + @last_family = nil + end + + def add(family_name, addrinfos) + @addrinfo_dict[family_name] = addrinfos + end + + def get + return nil if empty? + + if @addrinfo_dict.size == 1 + @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift } + end + + precedences = case @last_family + when :ipv4, nil then PRIORITY_ON_V6 + when :ipv6 then PRIORITY_ON_V4 + end + + precedences.each do |family_name| + addrinfo = @addrinfo_dict[family_name]&.shift + next unless addrinfo + + @last_family = family_name + return addrinfo + end + end + + def empty? + @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? } + end + + def any? + !empty? + end + end + private_constant :SelectableAddrinfos + + class NoHostnameResolutionQueue + def waiting_pipe + nil + end + + def add_resolved(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def add_error(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def get + nil + end + + def opened? + false + end + + def closed? + true + end + + def close_all + # Do nothing + end + end + private_constant :NoHostnameResolutionQueue + + class HostnameResolutionQueue + def initialize(size) + @size = size + @taken_count = 0 + @rpipe, @wpipe = IO.pipe + @queue = Queue.new + @mutex = Mutex.new + end + + def waiting_pipe + [@rpipe] + end + + def add_resolved(family, resolved_addrinfos) + @mutex.synchronize do + @queue.push [family, resolved_addrinfos] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def add_error(family, error) + @mutex.synchronize do + @queue.push [family, error] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def get + return nil if @queue.empty? + + res = nil + + @mutex.synchronize do + @rpipe.getbyte + res = @queue.pop + end + + @taken_count += 1 + close_all if @taken_count == @size + res + end + + def closed? + @rpipe.closed? + end + + def opened? + !closed? + end + + def close_all + @queue.close unless @queue.closed? + @rpipe.close unless @rpipe.closed? + @wpipe.close unless @wpipe.closed? + end + end + private_constant :HostnameResolutionQueue + + class ConnectingSockets + def initialize + @socket_dict = {} + end + + def all + @socket_dict.keys + end + + def add(socket, addrinfo) + @socket_dict[socket] = addrinfo + end + + def delete(socket) + @socket_dict.delete socket + end + + def empty? + @socket_dict.empty? + end + + def each + @socket_dict.keys.each do |socket| + yield socket + end + end + end + private_constant :ConnectingSockets + + def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) last_error = nil ret = nil @@ -663,6 +1176,7 @@ class Socket < BasicSocket ret end end + private_class_method :tcp_without_fast_fallback # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) @@ -1225,9 +1739,10 @@ class UDPSocket < IPSocket # The first element of the results, _mesg_, is the data received. # The second element, _sender_inet_addr_, is an array to represent the sender address. # - # When recvfrom(2) returns 0, - # Socket#recvfrom_nonblock returns an empty string as data. - # It means an empty packet. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but it may also mean + # an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the number of bytes to receive from the socket diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index 5e6c0668f6..4271e40cd8 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -51,7 +51,10 @@ DATA.each_line {|s| next end h[name] = default_value - COMMENTS[name] = comment + if comment + # Stop unintentional references + COMMENTS[name] = comment.gsub(/\b(Data|Kernel|Process|Set|Socket|Time)\b/, '\\\\\\&') + end } DEFS = h.to_a @@ -73,15 +76,11 @@ def each_name(pat) } end -erb_new = lambda do |src, safe, trim| - if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ - ERB.new(src, trim_mode: trim) - else - ERB.new(src, safe, trim) - end +erb_new = lambda do |src, trim| + ERB.new(src, trim_mode: trim) end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls") % each_const {|guard, name, default_value| #if !defined(<%=name%>) # if defined(HAVE_CONST_<%=name.upcase%>) @@ -95,7 +94,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls") % } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)") #if defined(<%=name%>) /* <%= COMMENTS[name] %> */ rb_define_const(rb_cSocket, <%=c_str name%>, INTEGER2NUM(<%=name%>)); @@ -104,7 +103,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name #endif EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs") % each_const {|guard, name, default_value| % if guard #if <%=guard%> @@ -154,7 +153,7 @@ def each_names_with_len(pat, prefix_optional=nil) } end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)") %if guard #ifdef <%=guard%> int <%=funcname%>(const char *str, long len, int *valp); @@ -164,7 +163,7 @@ int <%=funcname%>(const char *str, long len, int *valp); %end EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)") int <%=funcname%>(const char *str, long len, int *valp) { @@ -186,7 +185,7 @@ int } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)") %if guard #ifdef <%=guard%> <%=gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard)%> @@ -215,7 +214,7 @@ def reverse_each_name_with_prefix_optional(pat, prefix_pat) end end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)") <%=hash_var%> = st_init_numtable(); % reverse_each_name_with_prefix_optional(pat, prefix_pat) {|n,s| #ifdef <%=n%> @@ -224,7 +223,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_va % } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)") ID <%=func_name%>(int val) { @@ -235,7 +234,7 @@ ID } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)") ID <%=func_name%>(int val); EOS @@ -284,7 +283,7 @@ def_intern('rsock_intern_udp_optname', /\AUDP_/, "UDP_") def_intern('rsock_intern_scm_optname', /\ASCM_/, "SCM_") def_intern('rsock_intern_local_optname', /\ALOCAL_/, "LOCAL_") -result = erb_new.call(<<'EOS', nil, '%').result(binding) +result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ <%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| vardef }.join("\n") %> @@ -327,7 +326,7 @@ init_constants(void) EOS -header_result = erb_new.call(<<'EOS', nil, '%').result(binding) +header_result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ <%= gen_const_decls %> <%= NAME_TO_INT_DEFS.map {|decl, func| decl }.join("\n") %> @@ -423,8 +422,8 @@ AF_ISDN nil Integrated Services Digital Network PF_ISDN nil Integrated Services Digital Network AF_NATM nil Native ATM access PF_NATM nil Native ATM access -AF_SYSTEM -PF_SYSTEM +AF_SYSTEM nil Kernel event messages +PF_SYSTEM nil Kernel event messages AF_NETBIOS nil NetBIOS PF_NETBIOS nil NetBIOS AF_PPP nil Point-to-Point Protocol @@ -440,8 +439,8 @@ PF_PACKET nil Direct link-layer access AF_E164 nil CCITT (ITU-T) E.164 recommendation PF_XTP nil eXpress Transfer Protocol -PF_RTIP -PF_PIP +PF_RTIP nil Help Identify RTIP packets +PF_PIP nil Help Identify PIP packets AF_KEY nil Key management protocol, originally developed for usage with IPsec PF_KEY nil Key management protocol, originally developed for usage with IPsec AF_NETLINK nil Kernel user interface device @@ -666,6 +665,7 @@ SO_SETFIB nil Set the associated routing table for the socket (FreeBSD SO_RTABLE nil Set the routing table for this socket (OpenBSD) SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19) SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12) +SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows) SOPRI_INTERACTIVE nil Interactive socket priority SOPRI_NORMAL nil Normal socket priority @@ -745,6 +745,7 @@ SHUT_RDWR 2 Shut down the both sides of the socket IPV6_JOIN_GROUP nil Join a group membership IPV6_LEAVE_GROUP nil Leave a group membership +IPV6_MTU_DISCOVER nil Path MTU discovery IPV6_MULTICAST_HOPS nil IP6 multicast hops IPV6_MULTICAST_IF nil IP6 multicast interface IPV6_MULTICAST_LOOP nil IP6 multicast loopback @@ -759,6 +760,7 @@ IPV6_NEXTHOP nil Next hop address IPV6_PATHMTU nil Retrieve current path MTU IPV6_PKTINFO nil Receive packet information with datagram IPV6_RECVDSTOPTS nil Receive all IP6 options for response +IPV6_RECVERR nil Enable extended reliable error message passing IPV6_RECVHOPLIMIT nil Receive hop limit with datagram IPV6_RECVHOPOPTS nil Receive hop-by-hop options IPV6_RECVPKTINFO nil Receive destination IP address and incoming interface diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index 269edc4dad..090ba1a0c0 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -10,6 +10,22 @@ #include "rubysocket.h" +// GETADDRINFO_IMPL == 0 : call getaddrinfo/getnameinfo directly +// GETADDRINFO_IMPL == 1 : call getaddrinfo/getnameinfo without gvl (but uncancellable) +// GETADDRINFO_IMPL == 2 : call getaddrinfo/getnameinfo in a dedicated pthread +// (and if the call is interrupted, the pthread is detached) + +#ifndef GETADDRINFO_IMPL +# ifdef GETADDRINFO_EMU +# define GETADDRINFO_IMPL 0 +# elif !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__) +# define GETADDRINFO_IMPL 1 +# else +# define GETADDRINFO_IMPL 2 +# include "ruby/thread_native.h" +# endif +#endif + #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6)) #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0])) static const int lookup_order_table[] = { @@ -173,32 +189,6 @@ parse_numeric_port(const char *service, int *portp) } #endif -#ifndef GETADDRINFO_EMU -struct getaddrinfo_arg -{ - const char *node; - const char *service; - const struct addrinfo *hints; - struct addrinfo **res; -}; - -static void * -nogvl_getaddrinfo(void *arg) -{ - int ret; - struct getaddrinfo_arg *ptr = arg; - ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res); -#ifdef __linux__ - /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and - * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] - */ - if (ret == EAI_SYSTEM && errno == ENOENT) - ret = EAI_NONAME; -#endif - return (void *)(VALUE)ret; -} -#endif - static int numeric_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, @@ -302,7 +292,265 @@ rb_freeaddrinfo(struct rb_addrinfo *ai) xfree(ai); } -#ifndef GETADDRINFO_EMU +#if GETADDRINFO_IMPL == 0 + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai) +{ + return getaddrinfo(hostp, portp, hints, ai); +} + +#elif GETADDRINFO_IMPL == 1 + +struct getaddrinfo_arg +{ + const char *node; + const char *service; + const struct addrinfo *hints; + struct addrinfo **res; +}; + +static void * +nogvl_getaddrinfo(void *arg) +{ + int ret; + struct getaddrinfo_arg *ptr = arg; + ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res); +#ifdef __linux__ + /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and + * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] + */ + if (ret == EAI_SYSTEM && errno == ENOENT) + ret = EAI_NONAME; +#endif + return (void *)(VALUE)ret; +} + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai) +{ + struct getaddrinfo_arg arg; + MEMZERO(&arg, struct getaddrinfo_arg, 1); + arg.node = hostp; + arg.service = portp; + arg.hints = hints; + arg.res = ai; + return (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); +} + +#elif GETADDRINFO_IMPL == 2 + +struct getaddrinfo_arg +{ + char *node, *service; + struct addrinfo hints; + struct addrinfo *ai; + int err, gai_errno, refcount, done, cancelled; + rb_nativethread_lock_t lock; + rb_nativethread_cond_t cond; +}; + +static struct getaddrinfo_arg * +allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints) +{ + size_t hostp_offset = sizeof(struct getaddrinfo_arg); + size_t portp_offset = hostp_offset + (hostp ? strlen(hostp) + 1 : 0); + size_t bufsize = portp_offset + (portp ? strlen(portp) + 1 : 0); + + char *buf = malloc(bufsize); + if (!buf) { + rb_gc(); + buf = malloc(bufsize); + if (!buf) return NULL; + } + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)buf; + + if (hostp) { + arg->node = buf + hostp_offset; + strcpy(arg->node, hostp); + } + else { + arg->node = NULL; + } + + if (portp) { + arg->service = buf + portp_offset; + strcpy(arg->service, portp); + } + else { + arg->service = NULL; + } + + arg->hints = *hints; + arg->ai = NULL; + + arg->refcount = 2; + arg->done = arg->cancelled = 0; + + rb_nativethread_lock_initialize(&arg->lock); + rb_native_cond_initialize(&arg->cond); + + return arg; +} + +static void +free_getaddrinfo_arg(struct getaddrinfo_arg *arg) +{ + rb_native_cond_destroy(&arg->cond); + rb_nativethread_lock_destroy(&arg->lock); + free(arg); +} + +static void * +do_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + + int err, gai_errno; + err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai); + gai_errno = errno; +#ifdef __linux__ + /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and + * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] + */ + if (err == EAI_SYSTEM && errno == ENOENT) + err = EAI_NONAME; +#endif + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + { + arg->err = err; + arg->gai_errno = gai_errno; + if (arg->cancelled) { + freeaddrinfo(arg->ai); + } + else { + arg->done = 1; + rb_native_cond_signal(&arg->cond); + } + if (--arg->refcount == 0) need_free = 1; + } + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getaddrinfo_arg(arg); + + return 0; +} + +static void * +wait_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + while (!arg->done && !arg->cancelled) { + rb_native_cond_wait(&arg->cond, &arg->lock); + } + rb_nativethread_lock_unlock(&arg->lock); + return 0; +} + +static void +cancel_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + { + arg->cancelled = 1; + rb_native_cond_signal(&arg->cond); + } + rb_nativethread_lock_unlock(&arg->lock); +} + +static int +do_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg) +{ + int limit = 3, ret; + do { + // It is said that pthread_create may fail spuriously, so we follow the JDK and retry several times. + // + // https://bugs.openjdk.org/browse/JDK-8268605 + // https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1 + ret = pthread_create(th, 0, start_routine, arg); + } while (ret == EAGAIN && limit-- > 0); + return ret; +} + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai) +{ + int retry; + struct getaddrinfo_arg *arg; + int err = 0, gai_errno = 0; + +start: + retry = 0; + + arg = allocate_getaddrinfo_arg(hostp, portp, hints); + if (!arg) { + return EAI_MEMORY; + } + + pthread_t th; + if (do_pthread_create(&th, do_getaddrinfo, arg) != 0) { + int err = errno; + free_getaddrinfo_arg(arg); + errno = err; + return EAI_SYSTEM; + } + pthread_detach(th); + + rb_thread_call_without_gvl2(wait_getaddrinfo, arg, cancel_getaddrinfo, arg); + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + { + if (arg->done) { + err = arg->err; + gai_errno = arg->gai_errno; + if (err == 0) *ai = arg->ai; + } + else if (arg->cancelled) { + err = EAI_AGAIN; + } + else { + // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getaddrinfo. + // In this case, it could be !arg->done && !arg->cancelled. + arg->cancelled = 1; // to make do_getaddrinfo call freeaddrinfo + retry = 1; + } + if (--arg->refcount == 0) need_free = 1; + } + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getaddrinfo_arg(arg); + + // If the current thread is interrupted by asynchronous exception, the following raises the exception. + // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry. + rb_thread_check_ints(); + if (retry) goto start; + + /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread + * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno + * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */ + if (gai_errno) errno = gai_errno; + return err; +} + +#endif + +#if GETADDRINFO_IMPL == 0 + +int +rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) +{ + return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); +} + +#elif GETADDRINFO_IMPL == 1 + struct getnameinfo_arg { const struct sockaddr *sa; @@ -323,16 +571,11 @@ nogvl_getnameinfo(void *arg) ptr->serv, (socklen_t)ptr->servlen, ptr->flags); } -#endif - int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, int flags) + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) { -#ifdef GETADDRINFO_EMU - return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); -#else struct getnameinfo_arg arg; int ret; arg.sa = sa; @@ -344,17 +587,187 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, arg.flags = flags; ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0); return ret; -#endif +} + +#elif GETADDRINFO_IMPL == 2 + +struct getnameinfo_arg +{ + struct sockaddr *sa; + socklen_t salen; + int flags; + char *host; + size_t hostlen; + char *serv; + size_t servlen; + int err, gni_errno, refcount, done, cancelled; + rb_nativethread_lock_t lock; + rb_nativethread_cond_t cond; +}; + +static struct getnameinfo_arg * +allocate_getnameinfo_arg(const struct sockaddr *sa, socklen_t salen, size_t hostlen, size_t servlen, int flags) +{ + size_t sa_offset = sizeof(struct getnameinfo_arg); + size_t host_offset = sa_offset + salen; + size_t serv_offset = host_offset + hostlen; + size_t bufsize = serv_offset + servlen; + + char *buf = malloc(bufsize); + if (!buf) { + rb_gc(); + buf = malloc(bufsize); + if (!buf) return NULL; + } + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)buf; + + arg->sa = (struct sockaddr *)(buf + sa_offset); + memcpy(arg->sa, sa, salen); + arg->salen = salen; + arg->host = buf + host_offset; + arg->hostlen = hostlen; + arg->serv = buf + serv_offset; + arg->servlen = servlen; + arg->flags = flags; + + arg->refcount = 2; + arg->done = arg->cancelled = 0; + + rb_nativethread_lock_initialize(&arg->lock); + rb_native_cond_initialize(&arg->cond); + + return arg; +} + +static void +free_getnameinfo_arg(struct getnameinfo_arg *arg) +{ + rb_native_cond_destroy(&arg->cond); + rb_nativethread_lock_destroy(&arg->lock); + + free(arg); +} + +static void * +do_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + + int err, gni_errno; + err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags); + gni_errno = errno; + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + arg->err = err; + arg->gni_errno = gni_errno; + if (!arg->cancelled) { + arg->done = 1; + rb_native_cond_signal(&arg->cond); + } + if (--arg->refcount == 0) need_free = 1; + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getnameinfo_arg(arg); + + return 0; +} + +static void * +wait_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + while (!arg->done && !arg->cancelled) { + rb_native_cond_wait(&arg->cond, &arg->lock); + } + rb_nativethread_lock_unlock(&arg->lock); + return 0; } static void +cancel_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + arg->cancelled = 1; + rb_native_cond_signal(&arg->cond); + rb_nativethread_lock_unlock(&arg->lock); +} + +int +rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) +{ + int retry; + struct getnameinfo_arg *arg; + int err, gni_errno = 0; + +start: + retry = 0; + + arg = allocate_getnameinfo_arg(sa, salen, hostlen, servlen, flags); + if (!arg) { + return EAI_MEMORY; + } + + pthread_t th; + if (do_pthread_create(&th, do_getnameinfo, arg) != 0) { + int err = errno; + free_getnameinfo_arg(arg); + errno = err; + return EAI_SYSTEM; + } + pthread_detach(th); + + rb_thread_call_without_gvl2(wait_getnameinfo, arg, cancel_getnameinfo, arg); + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + if (arg->done) { + err = arg->err; + gni_errno = arg->gni_errno; + if (err == 0) { + if (host) memcpy(host, arg->host, hostlen); + if (serv) memcpy(serv, arg->serv, servlen); + } + } + else if (arg->cancelled) { + err = EAI_AGAIN; + } + else { + // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getnameinfo. + // In this case, it could be !arg->done && !arg->cancelled. + arg->cancelled = 1; + retry = 1; + } + if (--arg->refcount == 0) need_free = 1; + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getnameinfo_arg(arg); + + // If the current thread is interrupted by asynchronous exception, the following raises the exception. + // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry. + rb_thread_check_ints(); + if (retry) goto start; + + /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so + * calling code sees the correct errno */ + if (gni_errno) errno = gni_errno; + return err; +} + +#endif + +static void make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen) { int error; error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } } @@ -550,17 +963,7 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h } if (!resolved) { -#ifdef GETADDRINFO_EMU - error = getaddrinfo(hostp, portp, hints, &ai); -#else - struct getaddrinfo_arg arg; - MEMZERO(&arg, struct getaddrinfo_arg, 1); - arg.node = hostp; - arg.service = portp; - arg.hints = hints; - arg.res = &ai; - error = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); -#endif + error = rb_getaddrinfo(hostp, portp, hints, &ai); if (error == 0) { res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); res->allocated_by_malloc = 0; @@ -573,7 +976,7 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h if (hostp && hostp[strlen(hostp)-1] == '\n') { rb_raise(rb_eSocket, "newline at the end of hostname"); } - rsock_raise_socket_error("getaddrinfo", error); + rsock_raise_resolution_error("getaddrinfo", error); } return res; @@ -632,7 +1035,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup) error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } addr2 = rb_str_new2(hbuf); if (addr1 == Qnil) { @@ -1266,11 +1669,11 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r * RFC 4007: IPv6 Scoped Address Architecture * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API */ - error = getnameinfo(&sockaddr->addr, socklen, - hbuf, (socklen_t)sizeof(hbuf), NULL, 0, - NI_NUMERICHOST|NI_NUMERICSERV); + error = rb_getnameinfo(&sockaddr->addr, socklen, + hbuf, (socklen_t)sizeof(hbuf), NULL, 0, + NI_NUMERICHOST|NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } if (addr->sin6_port == 0) { rb_str_cat2(ret, hbuf); @@ -1634,11 +2037,11 @@ addrinfo_mdump(VALUE self) { char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; int error; - error = getnameinfo(&rai->addr.addr, rai->sockaddr_len, - hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), - NI_NUMERICHOST|NI_NUMERICSERV); + error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len, + hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), + NI_NUMERICHOST|NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); break; @@ -1980,11 +2383,11 @@ addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) if (rai->socktype == SOCK_DGRAM) flags |= NI_DGRAM; - error = getnameinfo(&rai->addr.addr, rai->sockaddr_len, - hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), - flags); + error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len, + hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), + flags); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); @@ -2614,12 +3017,12 @@ rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) void rsock_init_addrinfo(void) { + id_timeout = rb_intern("timeout"); + /* * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This * structure identifies an Internet host and a service. */ - id_timeout = rb_intern("timeout"); - rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject); rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 5f803ba0da..f486db4262 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -35,6 +35,7 @@ #ifdef _WIN32 # include <winsock2.h> # include <ws2tcpip.h> +# include <mswsock.h> # include <iphlpapi.h> # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL @@ -285,6 +286,7 @@ extern VALUE rb_cAddrinfo; extern VALUE rb_cSockOpt; extern VALUE rb_eSocket; +extern VALUE rb_eResolution; #ifdef SOCKS extern VALUE rb_cSOCKSSocket; @@ -307,7 +309,7 @@ VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *ai_ret VALUE rb_check_sockaddr_string_type(VALUE); -NORETURN(void rsock_raise_socket_error(const char *, int)); +NORETURN(void rsock_raise_resolution_error(const char *, int)); int rsock_family_arg(VALUE domain); int rsock_socktype_arg(VALUE type); @@ -459,6 +461,8 @@ VALUE rsock_write_nonblock(VALUE sock, VALUE buf, VALUE ex); void rsock_make_fd_nonblock(int fd); +int rsock_is_dgram(rb_io_t *fptr); + #if !defined HAVE_INET_NTOP && ! defined _WIN32 const char *inet_ntop(int, const void *, char *, size_t); #elif defined __MINGW32__ diff --git a/ext/socket/socket.c b/ext/socket/socket.c index eb74f7a936..c780d77cf6 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1313,7 +1313,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) saved_errno = errno; if (res) rb_freeaddrinfo(res); errno = saved_errno; - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); UNREACHABLE_RETURN(Qnil); } @@ -1654,8 +1654,7 @@ socket_s_ip_address_list(VALUE self) finish: save_errno = errno; - if (lc.lifc_buf != NULL) - xfree(lc.lifc_req); + xfree(lc.lifc_req); if (fd != -1) close(fd); errno = save_errno; diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c index 26ab76fc9f..a8475e3e60 100644 --- a/ext/socket/unixsocket.c +++ b/ext/socket/unixsocket.c @@ -540,7 +540,7 @@ unix_peeraddr(VALUE sock) * * Creates a pair of sockets connected to each other. * - * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * _type_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. * * _protocol_ should be a protocol defined in the domain. * 0 is default protocol for the domain. |