polyphony 0.98 → 0.99.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -1
- data/.rubocop.yml +3 -3
- data/.yardopts +30 -0
- data/CHANGELOG.md +11 -0
- data/LICENSE +1 -1
- data/README.md +63 -29
- data/Rakefile +1 -5
- data/TODO.md +0 -4
- data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
- data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
- data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
- data/docs/{main-concepts/extending.md → extending.md} +2 -9
- data/docs/faq.md +3 -16
- data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
- data/docs/link_rewriter.rb +16 -0
- data/docs/{getting-started/overview.md → overview.md} +1 -30
- data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
- data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
- data/examples/adapters/redis_client.rb +3 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_plain_ruby.rb +26 -0
- data/examples/io/https_server_sni_2.rb +14 -8
- data/ext/polyphony/backend_io_uring.c +154 -9
- data/ext/polyphony/backend_io_uring_context.c +21 -12
- data/ext/polyphony/backend_io_uring_context.h +12 -7
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/extconf.rb +25 -8
- data/ext/polyphony/fiber.c +79 -2
- data/ext/polyphony/io_extensions.c +53 -0
- data/ext/polyphony/libev.h +0 -2
- data/ext/polyphony/pipe.c +42 -2
- data/ext/polyphony/polyphony.c +345 -31
- data/ext/polyphony/polyphony.h +9 -2
- data/ext/polyphony/queue.c +181 -0
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +8 -1
- data/ext/polyphony/runqueue_ring_buffer.c +13 -0
- data/ext/polyphony/runqueue_ring_buffer.h +2 -1
- data/ext/polyphony/socket_extensions.c +6 -0
- data/ext/polyphony/thread.c +34 -2
- data/lib/polyphony/adapters/process.rb +11 -1
- data/lib/polyphony/adapters/sequel.rb +1 -1
- data/lib/polyphony/core/channel.rb +2 -0
- data/lib/polyphony/core/debug.rb +1 -1
- data/lib/polyphony/core/global_api.rb +25 -24
- data/lib/polyphony/core/resource_pool.rb +7 -6
- data/lib/polyphony/core/sync.rb +55 -2
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/core/timer.rb +8 -8
- data/lib/polyphony/extensions/exception.rb +2 -0
- data/lib/polyphony/extensions/fiber.rb +15 -13
- data/lib/polyphony/extensions/io.rb +161 -16
- data/lib/polyphony/extensions/kernel.rb +20 -2
- data/lib/polyphony/extensions/openssl.rb +101 -12
- data/lib/polyphony/extensions/pipe.rb +103 -7
- data/lib/polyphony/extensions/process.rb +13 -1
- data/lib/polyphony/extensions/socket.rb +93 -27
- data/lib/polyphony/extensions/thread.rb +9 -1
- data/lib/polyphony/extensions/timeout.rb +1 -1
- data/lib/polyphony/version.rb +2 -1
- data/lib/polyphony.rb +27 -7
- data/polyphony.gemspec +1 -8
- data/test/stress.rb +1 -1
- data/test/test_global_api.rb +45 -7
- data/test/test_io.rb +6 -7
- data/test/test_socket.rb +157 -0
- data/test/test_sync.rb +42 -1
- data/test/test_timer.rb +5 -5
- data/vendor/liburing/.github/workflows/build.yml +7 -16
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +23 -1
- data/vendor/liburing/Makefile +4 -3
- data/vendor/liburing/Makefile.common +1 -0
- data/vendor/liburing/README +48 -0
- data/vendor/liburing/configure +76 -6
- data/vendor/liburing/debian/changelog +11 -0
- data/vendor/liburing/debian/control +7 -16
- data/vendor/liburing/debian/liburing-dev.manpages +3 -6
- data/vendor/liburing/debian/liburing2.install +1 -0
- data/vendor/liburing/debian/liburing2.symbols +56 -0
- data/vendor/liburing/debian/rules +15 -68
- data/vendor/liburing/examples/Makefile +4 -0
- data/vendor/liburing/examples/io_uring-close-test.c +123 -0
- data/vendor/liburing/examples/io_uring-udp.c +1 -1
- data/vendor/liburing/examples/send-zerocopy.c +315 -56
- data/vendor/liburing/examples/ucontext-cp.c +2 -17
- data/vendor/liburing/liburing-ffi.pc.in +12 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +3 -3
- data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
- data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
- data/vendor/liburing/man/io_uring_check_version.3 +72 -0
- data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
- data/vendor/liburing/man/io_uring_major_version.3 +1 -0
- data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
- data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
- data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
- data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
- data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
- data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
- data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
- data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
- data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
- data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
- data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
- data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
- data/vendor/liburing/man/io_uring_register.2 +15 -9
- data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
- data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
- data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files.3 +60 -5
- data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_setup.2 +31 -2
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
- data/vendor/liburing/src/Makefile +25 -3
- data/vendor/liburing/src/ffi.c +15 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
- data/vendor/liburing/src/include/liburing.h +190 -148
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/lib.h +5 -16
- data/vendor/liburing/src/liburing-ffi.map +172 -0
- data/vendor/liburing/src/liburing.map +11 -0
- data/vendor/liburing/src/nolibc.c +9 -2
- data/vendor/liburing/src/queue.c +2 -2
- data/vendor/liburing/src/register.c +66 -96
- data/vendor/liburing/src/setup.c +5 -4
- data/vendor/liburing/src/version.c +21 -0
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/35fa71a030ca.c +3 -3
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/917257daa0fe.c +1 -1
- data/vendor/liburing/test/Makefile +27 -7
- data/vendor/liburing/test/a0908ae19763.c +2 -2
- data/vendor/liburing/test/a4c0b3decb33.c +2 -2
- data/vendor/liburing/test/accept-link.c +4 -4
- data/vendor/liburing/test/accept-reuse.c +5 -7
- data/vendor/liburing/test/accept.c +34 -31
- data/vendor/liburing/test/b19062a56726.c +1 -1
- data/vendor/liburing/test/buf-ring.c +58 -4
- data/vendor/liburing/test/ce593a6c480a.c +2 -2
- data/vendor/liburing/test/close-opath.c +2 -1
- data/vendor/liburing/test/connect.c +8 -0
- data/vendor/liburing/test/cq-overflow.c +14 -8
- data/vendor/liburing/test/d4ae271dfaae.c +1 -1
- data/vendor/liburing/test/defer-taskrun.c +64 -9
- data/vendor/liburing/test/defer.c +1 -1
- data/vendor/liburing/test/double-poll-crash.c +3 -3
- data/vendor/liburing/test/eeed8b54e0df.c +8 -3
- data/vendor/liburing/test/eploop.c +74 -0
- data/vendor/liburing/test/eventfd-ring.c +1 -1
- data/vendor/liburing/test/eventfd.c +1 -1
- data/vendor/liburing/test/evloop.c +73 -0
- data/vendor/liburing/test/exit-no-cleanup.c +1 -1
- data/vendor/liburing/test/fadvise.c +1 -1
- data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
- data/vendor/liburing/test/fd-pass.c +35 -16
- data/vendor/liburing/test/file-register.c +61 -0
- data/vendor/liburing/test/file-verify.c +2 -2
- data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
- data/vendor/liburing/test/fixed-link.c +1 -1
- data/vendor/liburing/test/fsnotify.c +118 -0
- data/vendor/liburing/test/hardlink.c +1 -1
- data/vendor/liburing/test/helpers.c +54 -2
- data/vendor/liburing/test/helpers.h +4 -0
- data/vendor/liburing/test/io-cancel.c +3 -1
- data/vendor/liburing/test/io_uring_passthrough.c +39 -8
- data/vendor/liburing/test/io_uring_setup.c +3 -80
- data/vendor/liburing/test/iopoll-overflow.c +118 -0
- data/vendor/liburing/test/iopoll.c +90 -4
- data/vendor/liburing/test/lfs-openat-write.c +7 -9
- data/vendor/liburing/test/lfs-openat.c +6 -8
- data/vendor/liburing/test/link_drain.c +31 -5
- data/vendor/liburing/test/madvise.c +1 -1
- data/vendor/liburing/test/msg-ring-flags.c +192 -0
- data/vendor/liburing/test/msg-ring-overflow.c +159 -0
- data/vendor/liburing/test/msg-ring.c +173 -13
- data/vendor/liburing/test/multicqes_drain.c +22 -19
- data/vendor/liburing/test/nvme.h +4 -3
- data/vendor/liburing/test/pipe-bug.c +95 -0
- data/vendor/liburing/test/poll-link.c +3 -3
- data/vendor/liburing/test/poll-many.c +41 -19
- data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
- data/vendor/liburing/test/poll-race-mshot.c +292 -0
- data/vendor/liburing/test/poll-race.c +105 -0
- data/vendor/liburing/test/poll.c +244 -26
- data/vendor/liburing/test/pollfree.c +5 -5
- data/vendor/liburing/test/read-before-exit.c +20 -3
- data/vendor/liburing/test/read-write.c +2 -0
- data/vendor/liburing/test/recv-multishot.c +96 -3
- data/vendor/liburing/test/reg-reg-ring.c +90 -0
- data/vendor/liburing/test/rename.c +1 -1
- data/vendor/liburing/test/ring-leak.c +0 -1
- data/vendor/liburing/test/ring-leak2.c +1 -1
- data/vendor/liburing/test/ringbuf-read.c +10 -6
- data/vendor/liburing/test/send-zerocopy.c +273 -103
- data/vendor/liburing/test/send_recv.c +7 -4
- data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
- data/vendor/liburing/test/single-issuer.c +7 -9
- data/vendor/liburing/test/skip-cqe.c +3 -4
- data/vendor/liburing/test/socket.c +0 -1
- data/vendor/liburing/test/sq-poll-dup.c +10 -3
- data/vendor/liburing/test/sq-poll-kthread.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +3 -2
- data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
- data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
- data/vendor/liburing/test/symlink.c +2 -1
- data/vendor/liburing/test/test.h +2 -1
- data/vendor/liburing/test/timeout-new.c +11 -7
- data/vendor/liburing/test/timeout.c +1 -2
- data/vendor/liburing/test/unlink.c +1 -1
- data/vendor/liburing/test/version.c +25 -0
- data/vendor/liburing/test/wakeup-hang.c +1 -1
- data/vendor/liburing/test/xattr.c +8 -4
- metadata +57 -44
- data/docs/_config.yml +0 -64
- data/docs/_includes/head.html +0 -40
- data/docs/_includes/title.html +0 -1
- data/docs/_sass/custom/custom.scss +0 -10
- data/docs/_sass/overrides.scss +0 -0
- data/docs/api-reference/exception.md +0 -31
- data/docs/api-reference/fiber.md +0 -425
- data/docs/api-reference/index.md +0 -9
- data/docs/api-reference/io.md +0 -36
- data/docs/api-reference/object.md +0 -99
- data/docs/api-reference/polyphony-baseexception.md +0 -33
- data/docs/api-reference/polyphony-cancel.md +0 -26
- data/docs/api-reference/polyphony-moveon.md +0 -24
- data/docs/api-reference/polyphony-net.md +0 -20
- data/docs/api-reference/polyphony-process.md +0 -28
- data/docs/api-reference/polyphony-resourcepool.md +0 -59
- data/docs/api-reference/polyphony-restart.md +0 -18
- data/docs/api-reference/polyphony-terminate.md +0 -18
- data/docs/api-reference/polyphony-threadpool.md +0 -67
- data/docs/api-reference/polyphony-throttler.md +0 -77
- data/docs/api-reference/polyphony.md +0 -36
- data/docs/api-reference/thread.md +0 -88
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +0 -10
- data/docs/getting-started/installing.md +0 -34
- data/vendor/liburing/debian/compat +0 -1
- data/vendor/liburing/debian/liburing1-udeb.install +0 -1
- data/vendor/liburing/debian/liburing1.install +0 -1
- data/vendor/liburing/debian/liburing1.symbols +0 -32
- /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
- /data/{docs → assets}/polyphony-logo.png +0 -0
- /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
@@ -4,11 +4,13 @@ require 'open3'
|
|
4
4
|
|
5
5
|
# Kernel extensions (methods available to all objects / call sites)
|
6
6
|
module ::Kernel
|
7
|
+
# @!visibility private
|
7
8
|
alias_method :orig_sleep, :sleep
|
8
9
|
|
10
|
+
# @!visibility private
|
9
11
|
alias_method :orig_backtick, :`
|
10
12
|
|
11
|
-
#
|
13
|
+
# @!visibility private
|
12
14
|
def `(cmd)
|
13
15
|
Open3.popen3(cmd) do |i, o, e, _t|
|
14
16
|
i.close
|
@@ -18,6 +20,7 @@ module ::Kernel
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
# @!visibility private
|
21
24
|
ARGV_GETS_LOOP = proc do |calling_fiber|
|
22
25
|
while (fn = ARGV.shift)
|
23
26
|
File.open(fn, 'r') do |f|
|
@@ -31,7 +34,10 @@ module ::Kernel
|
|
31
34
|
calling_fiber.transfer(e)
|
32
35
|
end
|
33
36
|
|
37
|
+
# @!visibility private
|
34
38
|
alias_method :orig_gets, :gets
|
39
|
+
|
40
|
+
# Reads a single line from STDIN
|
35
41
|
def gets(*_args)
|
36
42
|
if !ARGV.empty? || @gets_fiber
|
37
43
|
@gets_fiber ||= Fiber.new(&ARGV_GETS_LOOP)
|
@@ -45,7 +51,10 @@ module ::Kernel
|
|
45
51
|
$stdin.gets
|
46
52
|
end
|
47
53
|
|
54
|
+
# @!visibility private
|
48
55
|
alias_method :orig_p, :p
|
56
|
+
|
57
|
+
# @!visibility private
|
49
58
|
def p(*args)
|
50
59
|
strs = args.inject([]) do |m, a|
|
51
60
|
m << a.inspect << "\n"
|
@@ -54,13 +63,19 @@ module ::Kernel
|
|
54
63
|
args.size == 1 ? args.first : args
|
55
64
|
end
|
56
65
|
|
66
|
+
# @!visibility private
|
57
67
|
alias_method :orig_system, :system
|
68
|
+
|
69
|
+
# @!visibility private
|
58
70
|
def system(*args)
|
59
71
|
Kernel.system(*args)
|
60
72
|
end
|
61
73
|
|
62
74
|
class << self
|
75
|
+
# @!visibility private
|
63
76
|
alias_method :orig_system, :system
|
77
|
+
|
78
|
+
# @!visibility private
|
64
79
|
def system(*args)
|
65
80
|
waiter = nil
|
66
81
|
Open3.popen2(*args) do |i, o, t|
|
@@ -74,7 +89,10 @@ module ::Kernel
|
|
74
89
|
end
|
75
90
|
end
|
76
91
|
|
92
|
+
# @!visibility private
|
77
93
|
alias_method :orig_trap, :trap
|
94
|
+
|
95
|
+
# @!visibility private
|
78
96
|
def trap(sig, command = nil, &block)
|
79
97
|
return orig_trap(sig, command) if command.is_a? String
|
80
98
|
|
@@ -93,7 +111,7 @@ module ::Kernel
|
|
93
111
|
|
94
112
|
private
|
95
113
|
|
96
|
-
#
|
114
|
+
# @!visibility private
|
97
115
|
def pipe_to_eof(src, dest)
|
98
116
|
src.read_loop { |data| dest << data }
|
99
117
|
end
|
@@ -5,30 +5,40 @@ require_relative './socket'
|
|
5
5
|
|
6
6
|
# OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
|
7
7
|
class ::OpenSSL::SSL::SSLSocket
|
8
|
+
# @!visibility private
|
8
9
|
def __read_method__
|
9
10
|
:readpartial
|
10
11
|
end
|
11
12
|
|
13
|
+
# @!visibility private
|
12
14
|
alias_method :orig_initialize, :initialize
|
13
15
|
|
14
|
-
#
|
16
|
+
# Initializese a new SSL socket
|
17
|
+
#
|
18
|
+
# @param socket [TCPSocket] socket to wrap
|
19
|
+
# @param context [OpenSSL::SSL::SSLContext] optional SSL context
|
20
|
+
# @return [void]
|
15
21
|
def initialize(socket, context = nil)
|
16
22
|
socket = socket.respond_to?(:io) ? socket.io || socket : socket
|
17
23
|
context ? orig_initialize(socket, context) : orig_initialize(socket)
|
18
24
|
end
|
19
25
|
|
26
|
+
# Sets DONT_LINGER option
|
20
27
|
def dont_linger
|
21
28
|
io.dont_linger
|
22
29
|
end
|
23
30
|
|
31
|
+
# Sets NO_DELAY option
|
24
32
|
def no_delay
|
25
33
|
io.no_delay
|
26
34
|
end
|
27
35
|
|
36
|
+
# Sets REUSE_ADDR option
|
28
37
|
def reuse_addr
|
29
38
|
io.reuse_addr
|
30
39
|
end
|
31
40
|
|
41
|
+
# @!visibility private
|
32
42
|
def fill_rbuff
|
33
43
|
data = self.sysread(BLOCK_SIZE)
|
34
44
|
if data
|
@@ -38,7 +48,10 @@ class ::OpenSSL::SSL::SSLSocket
|
|
38
48
|
end
|
39
49
|
end
|
40
50
|
|
51
|
+
# @!visibility private
|
41
52
|
alias_method :orig_sysread, :sysread
|
53
|
+
|
54
|
+
# @!visibility private
|
42
55
|
def sysread(maxlen, buf = +'')
|
43
56
|
# ensure socket is non blocking
|
44
57
|
Polyphony.backend_verify_blocking_mode(io, false)
|
@@ -51,7 +64,10 @@ class ::OpenSSL::SSL::SSLSocket
|
|
51
64
|
end
|
52
65
|
end
|
53
66
|
|
67
|
+
# @!visibility private
|
54
68
|
alias_method :orig_syswrite, :syswrite
|
69
|
+
|
70
|
+
# @!visibility private
|
55
71
|
def syswrite(buf)
|
56
72
|
# ensure socket is non blocking
|
57
73
|
Polyphony.backend_verify_blocking_mode(io, false)
|
@@ -65,16 +81,35 @@ class ::OpenSSL::SSL::SSLSocket
|
|
65
81
|
end
|
66
82
|
end
|
67
83
|
|
84
|
+
# @!visibility private
|
68
85
|
def flush
|
69
|
-
#
|
70
|
-
# @sync = true
|
71
|
-
# do_write ""
|
72
|
-
# return self
|
73
|
-
# ensure
|
74
|
-
# @sync = osync
|
86
|
+
# warn "SSLSocket#flush is not yet implemented in Polyphony"
|
75
87
|
end
|
76
88
|
|
89
|
+
# @!visibility private
|
77
90
|
alias_method :orig_read, :read
|
91
|
+
|
92
|
+
# call-seq:
|
93
|
+
# socket.read -> string
|
94
|
+
# socket.read(maxlen) -> string
|
95
|
+
# socket.read(maxlen, buf) -> buf
|
96
|
+
# socket.read(maxlen, buf, buf_pos) -> buf
|
97
|
+
#
|
98
|
+
# Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
|
99
|
+
# the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
|
100
|
+
# buffer to read into, otherwise a new string is allocated. If `buf_pos` is
|
101
|
+
# given, reads into the given offset (in bytes) in the given buffer. If the
|
102
|
+
# given buffer offset is negative, it is calculated from the current end of
|
103
|
+
# the buffer (`-1` means the read data will be appended to the end of the
|
104
|
+
# buffer).
|
105
|
+
#
|
106
|
+
# If no bytes are available and `EOF` is not hit, this method will block until
|
107
|
+
# the socket is ready to read from.
|
108
|
+
#
|
109
|
+
# @param maxlen [Integer, nil] maximum bytes to read from socket
|
110
|
+
# @param buf [String, nil] buffer to read into
|
111
|
+
# @param buf_pos [Number] buffer position to read into
|
112
|
+
# @return [String] buffer used for reading
|
78
113
|
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
79
114
|
return readpartial(maxlen, buf, buf_pos) if buf
|
80
115
|
|
@@ -88,13 +123,35 @@ class ::OpenSSL::SSL::SSLSocket
|
|
88
123
|
buf
|
89
124
|
end
|
90
125
|
|
91
|
-
|
92
|
-
|
126
|
+
# call-seq:
|
127
|
+
# socket.readpartial(maxlen) -> string
|
128
|
+
# socket.readpartial(maxlen, buf) -> buf
|
129
|
+
# socket.readpartial(maxlen, buf, buf_pos) -> buf
|
130
|
+
# socket.readpartial(maxlen, buf, buf_pos, raise_on_eof) -> buf
|
131
|
+
#
|
132
|
+
# Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
|
133
|
+
# buffer to read into, otherwise a new string is allocated. If `buf_pos` is
|
134
|
+
# given, reads into the given offset (in bytes) in the given buffer. If the
|
135
|
+
# given buffer offset is negative, it is calculated from the current end of
|
136
|
+
# the buffer (`-1` means the read data will be appended to the end of the
|
137
|
+
# buffer). If `raise_on_eof` is `true` (the default,) an `EOFError` will be
|
138
|
+
# raised on `EOF`, otherwise `nil` will be returned.
|
139
|
+
#
|
140
|
+
# If no bytes are available and `EOF` is not hit, this method will block until
|
141
|
+
# the socket is ready to read from.
|
142
|
+
#
|
143
|
+
# @param maxlen [Integer, nil] maximum bytes to read from socket
|
144
|
+
# @param buf [String, nil] buffer to read into
|
145
|
+
# @param buf_pos [Number] buffer position to read into
|
146
|
+
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
147
|
+
# @return [String, nil] buffer used for reading or nil on `EOF`
|
148
|
+
def readpartial(maxlen, buf = +'', buf_pos = 0, raise_on_eof = true)
|
149
|
+
if buf_pos != 0
|
93
150
|
if (result = sysread(maxlen, +''))
|
94
|
-
if
|
151
|
+
if buf_pos == -1
|
95
152
|
result = buf + result
|
96
153
|
else
|
97
|
-
result = buf[0...
|
154
|
+
result = buf[0...buf_pos] + result
|
98
155
|
end
|
99
156
|
end
|
100
157
|
else
|
@@ -105,6 +162,18 @@ class ::OpenSSL::SSL::SSLSocket
|
|
105
162
|
result
|
106
163
|
end
|
107
164
|
|
165
|
+
# call-seq:
|
166
|
+
# socket.recv_loop { |data| ... }
|
167
|
+
# socket.recv_loop(maxlen) { |data| ... }
|
168
|
+
# socket.read_loop { |data| ... }
|
169
|
+
# socket.read_loop(maxlen) { |data| ... }
|
170
|
+
#
|
171
|
+
# Receives up to `maxlen` bytes at a time in an infinite loop. Read buffers
|
172
|
+
# will be passed to the given block.
|
173
|
+
#
|
174
|
+
# @param maxlen [Integer] maximum bytes to receive
|
175
|
+
# @yield [String] handler block
|
176
|
+
# @return [void]
|
108
177
|
def read_loop(maxlen = 8192)
|
109
178
|
while (data = sysread(maxlen))
|
110
179
|
yield data
|
@@ -112,7 +181,10 @@ class ::OpenSSL::SSL::SSLSocket
|
|
112
181
|
end
|
113
182
|
alias_method :recv_loop, :read_loop
|
114
183
|
|
184
|
+
# @!visibility private
|
115
185
|
alias_method :orig_peeraddr, :peeraddr
|
186
|
+
|
187
|
+
# @!visibility private
|
116
188
|
def peeraddr(_ = nil)
|
117
189
|
orig_peeraddr
|
118
190
|
end
|
@@ -122,7 +194,12 @@ end
|
|
122
194
|
class ::OpenSSL::SSL::SSLServer
|
123
195
|
attr_reader :ctx
|
124
196
|
|
197
|
+
# @!visibility private
|
125
198
|
alias_method :orig_accept, :accept
|
199
|
+
|
200
|
+
# Accepts a new connection and performs SSL handshake.
|
201
|
+
#
|
202
|
+
# @return [OpenSSL::SSL::SSLSocket] accepted SSL connection
|
126
203
|
def accept
|
127
204
|
# when @ctx.servername_cb is set, we use a worker thread to run the
|
128
205
|
# ssl.accept call. We need to do this because:
|
@@ -165,6 +242,7 @@ class ::OpenSSL::SSL::SSLServer
|
|
165
242
|
end
|
166
243
|
end
|
167
244
|
|
245
|
+
# @!visibility private
|
168
246
|
def start_accept_worker_thread
|
169
247
|
fiber = Fiber.current
|
170
248
|
@accept_worker_thread = Thread.new do
|
@@ -187,20 +265,31 @@ class ::OpenSSL::SSL::SSLServer
|
|
187
265
|
@accept_worker_fiber = receive
|
188
266
|
end
|
189
267
|
|
268
|
+
# @!visibility private
|
190
269
|
def use_accept_worker_thread?
|
191
270
|
!!@ctx.servername_cb
|
192
271
|
end
|
193
272
|
|
273
|
+
# @!visibility private
|
194
274
|
alias_method :orig_close, :close
|
275
|
+
|
276
|
+
# @!visibility private
|
195
277
|
def close
|
196
278
|
@accept_worker_thread&.kill
|
197
279
|
orig_close
|
198
280
|
end
|
199
281
|
|
282
|
+
# call-seq:
|
283
|
+
# socket.accept_loop { |conn| ... }
|
284
|
+
#
|
285
|
+
# Accepts incoming connections in an infinite loop.
|
286
|
+
#
|
287
|
+
# @yield [OpenSSL::SSL::SSLSocket] block receiving accepted sockets
|
288
|
+
# @return [void]
|
200
289
|
def accept_loop(ignore_errors = true)
|
201
290
|
loop do
|
202
291
|
yield accept
|
203
|
-
rescue
|
292
|
+
rescue OpenSSL::SSL::SSLError, SystemCallError => e
|
204
293
|
raise e unless ignore_errors
|
205
294
|
end
|
206
295
|
end
|
@@ -1,20 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Pipe instance
|
3
|
+
# A Pipe instance represents a UNIX pipe that can be read and written to. This
|
4
|
+
# API is an alternative to the `IO.pipe` API, that returns two separate fds, one
|
5
|
+
# for reading and one for writing. Instead, `Polyphony::Pipe` encapsulates the
|
6
|
+
# two fds in a single object, providing methods that enable us to treat the pipe
|
7
|
+
# as a normal IO object.
|
4
8
|
class Polyphony::Pipe
|
9
|
+
# @!visibility private
|
5
10
|
def __read_method__
|
6
11
|
:backend_read
|
7
12
|
end
|
8
13
|
|
14
|
+
# @!visibility private
|
9
15
|
def __write_method__
|
10
16
|
:backend_write
|
11
17
|
end
|
12
18
|
|
19
|
+
# Reads a single byte from the pipe.
|
20
|
+
#
|
21
|
+
# @return [Integer, nil] byte value
|
13
22
|
def getbyte
|
14
23
|
char = getc
|
15
24
|
char ? char.getbyte(0) : nil
|
16
25
|
end
|
17
26
|
|
27
|
+
# Reads a single character from the pipe.
|
28
|
+
#
|
29
|
+
# @return |String, nil] read character
|
18
30
|
def getc
|
19
31
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
20
32
|
|
@@ -25,6 +37,12 @@ class Polyphony::Pipe
|
|
25
37
|
nil
|
26
38
|
end
|
27
39
|
|
40
|
+
# Reads from the pipe.
|
41
|
+
#
|
42
|
+
# @param len [Integer, nil] maximum bytes to read
|
43
|
+
# @param buf [String, nil] buffer to read into
|
44
|
+
# @param buf_pos [Integer] buffer position to read into
|
45
|
+
# @return [String] read data
|
28
46
|
def read(len = nil, buf = nil, buf_pos = 0)
|
29
47
|
if buf
|
30
48
|
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
@@ -39,22 +57,48 @@ class Polyphony::Pipe
|
|
39
57
|
already_read
|
40
58
|
end
|
41
59
|
|
42
|
-
|
43
|
-
|
60
|
+
# Reads from the pipe.
|
61
|
+
#
|
62
|
+
# @param len [Integer, nil] maximum bytes to read
|
63
|
+
# @param buf [String, nil] buffer to read into
|
64
|
+
# @param buf_pos [Integer] buffer position to read into
|
65
|
+
# @param raise_on_eof [boolean] whether to raise an error if EOF is detected
|
66
|
+
# @return [String] read data
|
67
|
+
def readpartial(len, buf = +'', buf_pos = 0, raise_on_eof = true)
|
68
|
+
result = Polyphony.backend_read(self, buf, len, false, buf_pos)
|
44
69
|
raise EOFError if !result && raise_on_eof
|
45
70
|
|
46
71
|
result
|
47
72
|
end
|
48
73
|
|
49
|
-
|
50
|
-
|
74
|
+
# Writes to the pipe.
|
75
|
+
|
76
|
+
# @param buf [String] data to write
|
77
|
+
# @param args [any] further arguments to pass to Polyphony.backend_write
|
78
|
+
# @return [Integer] bytes written
|
79
|
+
def write(buf, *args)
|
80
|
+
Polyphony.backend_write(self, buf, *args)
|
51
81
|
end
|
52
82
|
|
53
|
-
|
54
|
-
|
83
|
+
# Writes to the pipe.
|
84
|
+
|
85
|
+
# @param buf [String] data to write
|
86
|
+
# @return [Integer] bytes written
|
87
|
+
def <<(buf)
|
88
|
+
Polyphony.backend_write(self, buf)
|
55
89
|
self
|
56
90
|
end
|
57
91
|
|
92
|
+
# call-seq:
|
93
|
+
# pipe.gets(limit, chomp)
|
94
|
+
# pipe.gets(separator, limit, chomp)
|
95
|
+
#
|
96
|
+
# Reads a single line from the pipe.
|
97
|
+
#
|
98
|
+
# @param sep [String] line separator
|
99
|
+
# @param _limit [Integer, nil] line length limit
|
100
|
+
# @param _chomp [boolean, nil] whether to chomp the read line
|
101
|
+
# @return [String, nil] read line
|
58
102
|
def gets(sep = $/, _limit = nil, _chomp: nil)
|
59
103
|
if sep.is_a?(Integer)
|
60
104
|
sep = $/
|
@@ -84,9 +128,14 @@ class Polyphony::Pipe
|
|
84
128
|
# def putc(obj)
|
85
129
|
# end
|
86
130
|
|
131
|
+
# @!visibility private
|
87
132
|
LINEFEED = "\n"
|
133
|
+
# @!visibility private
|
88
134
|
LINEFEED_RE = /\n$/.freeze
|
89
135
|
|
136
|
+
# Writes a line with line feed to the pipe.
|
137
|
+
#
|
138
|
+
# @param args [Array] zero or more lines
|
90
139
|
def puts(*args)
|
91
140
|
if args.empty?
|
92
141
|
write LINEFEED
|
@@ -121,22 +170,55 @@ class Polyphony::Pipe
|
|
121
170
|
# def readlines(sep = $/, limit = nil, chomp: nil)
|
122
171
|
# end
|
123
172
|
|
173
|
+
# @!visibility private
|
124
174
|
def write_nonblock(string, _options = {})
|
125
175
|
write(string)
|
126
176
|
end
|
127
177
|
|
178
|
+
# @!visibility private
|
128
179
|
def read_nonblock(maxlen, buf = nil, _options = nil)
|
129
180
|
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
130
181
|
end
|
131
182
|
|
183
|
+
# Runs a read loop.
|
184
|
+
#
|
185
|
+
# @param maxlen [Integer] maximum bytes to read
|
186
|
+
# @yield [String] read block
|
187
|
+
# @return [void]
|
132
188
|
def read_loop(maxlen = 8192, &block)
|
133
189
|
Polyphony.backend_read_loop(self, maxlen, &block)
|
134
190
|
end
|
135
191
|
|
192
|
+
# call-seq:
|
193
|
+
# pipe.feed_loop(receiver, method)
|
194
|
+
# pipe.feed_loop(receiver, method) { |result| ... }
|
195
|
+
#
|
196
|
+
# Receives data from the pipe in an infinite loop, passing the data to the
|
197
|
+
# given receiver using the given method. If a block is given, the result of
|
198
|
+
# the method call to the receiver is passed to the block.
|
199
|
+
#
|
200
|
+
# This method can be used to feed data into parser objects. The following
|
201
|
+
# example shows how to feed data from a pipe directly into a MessagePack
|
202
|
+
# unpacker:
|
203
|
+
#
|
204
|
+
# unpacker = MessagePack::Unpacker.new
|
205
|
+
# buffer = []
|
206
|
+
# reader = spin do
|
207
|
+
# pipe.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
|
208
|
+
# end
|
209
|
+
#
|
210
|
+
# @param receiver [any] receiver object
|
211
|
+
# @param method [Symbol] method to call
|
212
|
+
# @yield [any] block to handle result of method call to receiver
|
213
|
+
# @return [void]
|
136
214
|
def feed_loop(receiver, method = :call, &block)
|
137
215
|
Polyphony.backend_feed_loop(self, receiver, method, &block)
|
138
216
|
end
|
139
217
|
|
218
|
+
# Waits for pipe to become readable.
|
219
|
+
#
|
220
|
+
# @param timeout [Number, nil] optional timeout in seconds
|
221
|
+
# @return [Polyphony::Pipe] self
|
140
222
|
def wait_readable(timeout = nil)
|
141
223
|
if timeout
|
142
224
|
move_on_after(timeout) do
|
@@ -149,6 +231,10 @@ class Polyphony::Pipe
|
|
149
231
|
end
|
150
232
|
end
|
151
233
|
|
234
|
+
# Waits for pipe to become writeable.
|
235
|
+
#
|
236
|
+
# @param timeout [Number, nil] optional timeout in seconds
|
237
|
+
# @return [Polyphony::Pipe] self
|
152
238
|
def wait_writable(timeout = nil)
|
153
239
|
if timeout
|
154
240
|
move_on_after(timeout) do
|
@@ -161,11 +247,21 @@ class Polyphony::Pipe
|
|
161
247
|
end
|
162
248
|
end
|
163
249
|
|
250
|
+
# Splices to the pipe from the given source.
|
251
|
+
#
|
252
|
+
# @param src [IO] source to splice from
|
253
|
+
# @param maxlen [Integer] maximum bytes to splice
|
254
|
+
# @return [Integer] bytes spliced
|
164
255
|
def splice_from(src, maxlen)
|
165
256
|
Polyphony.backend_splice(src, self, maxlen)
|
166
257
|
end
|
167
258
|
|
168
259
|
if RUBY_PLATFORM =~ /linux/
|
260
|
+
# Tees to the pipe from the given source.
|
261
|
+
#
|
262
|
+
# @param src [IO] source to tee from
|
263
|
+
# @param maxlen [Integer] maximum bytes to tee
|
264
|
+
# @return [Integer] bytes teed
|
169
265
|
def tee_from(src, maxlen)
|
170
266
|
Polyphony.backend_tee(src, self, maxlen)
|
171
267
|
end
|
@@ -1,16 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Overrides for Process
|
3
|
+
# Overrides for Process module
|
4
4
|
module ::Process
|
5
5
|
class << self
|
6
|
+
# @!visibility private
|
6
7
|
alias_method :orig_detach, :detach
|
8
|
+
|
9
|
+
# Detaches the given pid and returns a fiber waiting on it.
|
10
|
+
#
|
11
|
+
# @param pid [Integer] child pid
|
12
|
+
# @return [Fiber] new fiber waiting on pid
|
7
13
|
def detach(pid)
|
8
14
|
fiber = spin { Polyphony.backend_waitpid(pid) }
|
9
15
|
fiber.define_singleton_method(:pid) { pid }
|
10
16
|
fiber
|
11
17
|
end
|
12
18
|
|
19
|
+
# @!visibility private
|
13
20
|
alias_method :orig_daemon, :daemon
|
21
|
+
|
22
|
+
# Starts a daemon with the given arguments.
|
23
|
+
#
|
24
|
+
# @param args [any] arguments to pass to daemon
|
25
|
+
# @return [Integer] daemon pid
|
14
26
|
def daemon(*args)
|
15
27
|
orig_daemon(*args)
|
16
28
|
Polyphony.original_pid = Process.pid
|