polyphony 0.84 → 0.86
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/examples/core/multi_suspend.rb +39 -0
- data/examples/core/shutdown_all_children.rb +41 -0
- data/examples/io/gzip.rb +8 -0
- data/examples/io/splice_echo_server.rb +15 -0
- data/ext/polyphony/backend_io_uring.c +57 -31
- data/ext/polyphony/io_extensions.c +137 -26
- data/lib/polyphony/extensions/fiber.rb +3 -1
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/extensions/pipe.rb +4 -0
- data/lib/polyphony/extensions/socket.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/test_backend.rb +1 -1
- data/test/test_fiber.rb +5 -2
- data/test/test_signal.rb +3 -3
- data/vendor/liburing/.github/pull_request_template.md +86 -0
- data/vendor/liburing/.github/workflows/build.yml +85 -0
- data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
- data/vendor/liburing/.gitignore +149 -0
- data/vendor/liburing/COPYING +502 -0
- data/vendor/liburing/COPYING.GPL +339 -0
- data/vendor/liburing/LICENSE +7 -0
- data/vendor/liburing/Makefile +82 -0
- data/vendor/liburing/Makefile.common +5 -0
- data/vendor/liburing/Makefile.quiet +11 -0
- data/vendor/liburing/README +46 -0
- data/vendor/liburing/configure +486 -0
- data/vendor/liburing/debian/README.Debian +7 -0
- data/vendor/liburing/debian/changelog +27 -0
- data/vendor/liburing/debian/compat +1 -0
- data/vendor/liburing/debian/control +48 -0
- data/vendor/liburing/debian/copyright +49 -0
- data/vendor/liburing/debian/liburing-dev.install +4 -0
- data/vendor/liburing/debian/liburing-dev.manpages +6 -0
- data/vendor/liburing/debian/liburing1-udeb.install +1 -0
- data/vendor/liburing/debian/liburing1.install +1 -0
- data/vendor/liburing/debian/liburing1.symbols +32 -0
- data/vendor/liburing/debian/patches/series +1 -0
- data/vendor/liburing/debian/rules +81 -0
- data/vendor/liburing/debian/source/format +1 -0
- data/vendor/liburing/debian/source/local-options +2 -0
- data/vendor/liburing/debian/source/options +1 -0
- data/vendor/liburing/debian/watch +3 -0
- data/vendor/liburing/examples/Makefile +38 -0
- data/vendor/liburing/examples/io_uring-cp.c +282 -0
- data/vendor/liburing/examples/io_uring-test.c +112 -0
- data/vendor/liburing/examples/link-cp.c +193 -0
- data/vendor/liburing/examples/ucontext-cp.c +273 -0
- data/vendor/liburing/liburing.pc.in +12 -0
- data/vendor/liburing/liburing.spec +66 -0
- data/vendor/liburing/make-debs.sh +53 -0
- data/vendor/liburing/man/io_uring.7 +754 -0
- data/vendor/liburing/man/io_uring_cq_advance.3 +35 -0
- data/vendor/liburing/man/io_uring_cq_ready.3 +25 -0
- data/vendor/liburing/man/io_uring_cqe_get_data.3 +34 -0
- data/vendor/liburing/man/io_uring_cqe_seen.3 +32 -0
- data/vendor/liburing/man/io_uring_enter.2 +1483 -0
- data/vendor/liburing/man/io_uring_free_probe.3 +24 -0
- data/vendor/liburing/man/io_uring_get_probe.3 +29 -0
- data/vendor/liburing/man/io_uring_get_sqe.3 +38 -0
- data/vendor/liburing/man/io_uring_opcode_supported.3 +29 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +58 -0
- data/vendor/liburing/man/io_uring_prep_read.3 +50 -0
- data/vendor/liburing/man/io_uring_prep_read_fixed.3 +54 -0
- data/vendor/liburing/man/io_uring_prep_readv.3 +51 -0
- data/vendor/liburing/man/io_uring_prep_readv2.3 +79 -0
- data/vendor/liburing/man/io_uring_prep_write.3 +50 -0
- data/vendor/liburing/man/io_uring_prep_write_fixed.3 +54 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +51 -0
- data/vendor/liburing/man/io_uring_prep_writev2.3 +78 -0
- data/vendor/liburing/man/io_uring_queue_exit.3 +27 -0
- data/vendor/liburing/man/io_uring_queue_init.3 +44 -0
- data/vendor/liburing/man/io_uring_register.2 +688 -0
- data/vendor/liburing/man/io_uring_register_buffers.3 +41 -0
- data/vendor/liburing/man/io_uring_register_files.3 +35 -0
- data/vendor/liburing/man/io_uring_setup.2 +534 -0
- data/vendor/liburing/man/io_uring_sq_ready.3 +25 -0
- data/vendor/liburing/man/io_uring_sq_space_left.3 +25 -0
- data/vendor/liburing/man/io_uring_sqe_set_data.3 +30 -0
- data/vendor/liburing/man/io_uring_sqe_set_flags.3 +60 -0
- data/vendor/liburing/man/io_uring_sqring_wait.3 +30 -0
- data/vendor/liburing/man/io_uring_submit.3 +29 -0
- data/vendor/liburing/man/io_uring_submit_and_wait.3 +34 -0
- data/vendor/liburing/man/io_uring_submit_and_wait_timeout.3 +49 -0
- data/vendor/liburing/man/io_uring_unregister_buffers.3 +26 -0
- data/vendor/liburing/man/io_uring_unregister_files.3 +26 -0
- data/vendor/liburing/man/io_uring_wait_cqe.3 +33 -0
- data/vendor/liburing/man/io_uring_wait_cqe_nr.3 +36 -0
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +39 -0
- data/vendor/liburing/man/io_uring_wait_cqes.3 +46 -0
- data/vendor/liburing/src/Makefile +89 -0
- data/vendor/liburing/src/arch/aarch64/syscall.h +95 -0
- data/vendor/liburing/src/arch/generic/lib.h +21 -0
- data/vendor/liburing/src/arch/generic/syscall.h +87 -0
- data/vendor/liburing/src/arch/syscall-defs.h +67 -0
- data/vendor/liburing/src/arch/x86/lib.h +32 -0
- data/vendor/liburing/src/arch/x86/syscall.h +160 -0
- data/vendor/liburing/src/include/liburing/barrier.h +81 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +442 -0
- data/vendor/liburing/src/include/liburing.h +921 -0
- data/vendor/liburing/src/int_flags.h +8 -0
- data/vendor/liburing/src/lib.h +57 -0
- data/vendor/liburing/src/liburing.map +53 -0
- data/vendor/liburing/src/nolibc.c +48 -0
- data/vendor/liburing/src/queue.c +403 -0
- data/vendor/liburing/src/register.c +293 -0
- data/vendor/liburing/src/setup.c +332 -0
- data/vendor/liburing/src/syscall.c +47 -0
- data/vendor/liburing/src/syscall.h +103 -0
- data/vendor/liburing/test/232c93d07b74-test.c +306 -0
- data/vendor/liburing/test/35fa71a030ca-test.c +329 -0
- data/vendor/liburing/test/500f9fbadef8-test.c +89 -0
- data/vendor/liburing/test/7ad0e4b2f83c-test.c +93 -0
- data/vendor/liburing/test/8a9973408177-test.c +106 -0
- data/vendor/liburing/test/917257daa0fe-test.c +53 -0
- data/vendor/liburing/test/Makefile +244 -0
- data/vendor/liburing/test/a0908ae19763-test.c +58 -0
- data/vendor/liburing/test/a4c0b3decb33-test.c +180 -0
- data/vendor/liburing/test/accept-link.c +254 -0
- data/vendor/liburing/test/accept-reuse.c +164 -0
- data/vendor/liburing/test/accept-test.c +79 -0
- data/vendor/liburing/test/accept.c +477 -0
- data/vendor/liburing/test/across-fork.c +283 -0
- data/vendor/liburing/test/b19062a56726-test.c +53 -0
- data/vendor/liburing/test/b5837bd5311d-test.c +77 -0
- data/vendor/liburing/test/ce593a6c480a-test.c +136 -0
- data/vendor/liburing/test/close-opath.c +122 -0
- data/vendor/liburing/test/config +10 -0
- data/vendor/liburing/test/connect.c +398 -0
- data/vendor/liburing/test/cq-full.c +96 -0
- data/vendor/liburing/test/cq-overflow.c +294 -0
- data/vendor/liburing/test/cq-peek-batch.c +102 -0
- data/vendor/liburing/test/cq-ready.c +94 -0
- data/vendor/liburing/test/cq-size.c +64 -0
- data/vendor/liburing/test/d4ae271dfaae-test.c +96 -0
- data/vendor/liburing/test/d77a67ed5f27-test.c +65 -0
- data/vendor/liburing/test/defer.c +307 -0
- data/vendor/liburing/test/double-poll-crash.c +185 -0
- data/vendor/liburing/test/drop-submit.c +92 -0
- data/vendor/liburing/test/eeed8b54e0df-test.c +114 -0
- data/vendor/liburing/test/empty-eownerdead.c +45 -0
- data/vendor/liburing/test/eventfd-disable.c +151 -0
- data/vendor/liburing/test/eventfd-reg.c +76 -0
- data/vendor/liburing/test/eventfd-ring.c +97 -0
- data/vendor/liburing/test/eventfd.c +112 -0
- data/vendor/liburing/test/exec-target.c +6 -0
- data/vendor/liburing/test/exit-no-cleanup.c +117 -0
- data/vendor/liburing/test/fadvise.c +202 -0
- data/vendor/liburing/test/fallocate.c +249 -0
- data/vendor/liburing/test/fc2a85cb02ef-test.c +131 -0
- data/vendor/liburing/test/file-register.c +858 -0
- data/vendor/liburing/test/file-update.c +173 -0
- data/vendor/liburing/test/file-verify.c +629 -0
- data/vendor/liburing/test/files-exit-hang-poll.c +128 -0
- data/vendor/liburing/test/files-exit-hang-timeout.c +134 -0
- data/vendor/liburing/test/fixed-link.c +90 -0
- data/vendor/liburing/test/fpos.c +252 -0
- data/vendor/liburing/test/fsync.c +224 -0
- data/vendor/liburing/test/hardlink.c +136 -0
- data/vendor/liburing/test/helpers.c +135 -0
- data/vendor/liburing/test/helpers.h +67 -0
- data/vendor/liburing/test/io-cancel.c +550 -0
- data/vendor/liburing/test/io_uring_enter.c +296 -0
- data/vendor/liburing/test/io_uring_register.c +676 -0
- data/vendor/liburing/test/io_uring_setup.c +192 -0
- data/vendor/liburing/test/iopoll.c +372 -0
- data/vendor/liburing/test/lfs-openat-write.c +119 -0
- data/vendor/liburing/test/lfs-openat.c +275 -0
- data/vendor/liburing/test/link-timeout.c +1107 -0
- data/vendor/liburing/test/link.c +496 -0
- data/vendor/liburing/test/link_drain.c +229 -0
- data/vendor/liburing/test/madvise.c +195 -0
- data/vendor/liburing/test/mkdir.c +108 -0
- data/vendor/liburing/test/msg-ring.c +234 -0
- data/vendor/liburing/test/multicqes_drain.c +387 -0
- data/vendor/liburing/test/nop-all-sizes.c +99 -0
- data/vendor/liburing/test/nop.c +115 -0
- data/vendor/liburing/test/open-close.c +261 -0
- data/vendor/liburing/test/openat2.c +308 -0
- data/vendor/liburing/test/personality.c +204 -0
- data/vendor/liburing/test/pipe-eof.c +83 -0
- data/vendor/liburing/test/pipe-reuse.c +105 -0
- data/vendor/liburing/test/poll-cancel-ton.c +135 -0
- data/vendor/liburing/test/poll-cancel.c +228 -0
- data/vendor/liburing/test/poll-link.c +230 -0
- data/vendor/liburing/test/poll-many.c +208 -0
- data/vendor/liburing/test/poll-mshot-update.c +273 -0
- data/vendor/liburing/test/poll-ring.c +48 -0
- data/vendor/liburing/test/poll-v-poll.c +353 -0
- data/vendor/liburing/test/poll.c +109 -0
- data/vendor/liburing/test/pollfree.c +426 -0
- data/vendor/liburing/test/probe.c +135 -0
- data/vendor/liburing/test/read-write.c +876 -0
- data/vendor/liburing/test/register-restrictions.c +633 -0
- data/vendor/liburing/test/rename.c +135 -0
- data/vendor/liburing/test/ring-leak.c +173 -0
- data/vendor/liburing/test/ring-leak2.c +249 -0
- data/vendor/liburing/test/rsrc_tags.c +449 -0
- data/vendor/liburing/test/runtests-loop.sh +16 -0
- data/vendor/liburing/test/runtests.sh +170 -0
- data/vendor/liburing/test/rw_merge_test.c +97 -0
- data/vendor/liburing/test/self.c +91 -0
- data/vendor/liburing/test/send_recv.c +286 -0
- data/vendor/liburing/test/send_recvmsg.c +345 -0
- data/vendor/liburing/test/sendmsg_fs_cve.c +200 -0
- data/vendor/liburing/test/shared-wq.c +84 -0
- data/vendor/liburing/test/short-read.c +75 -0
- data/vendor/liburing/test/shutdown.c +165 -0
- data/vendor/liburing/test/sigfd-deadlock.c +74 -0
- data/vendor/liburing/test/skip-cqe.c +429 -0
- data/vendor/liburing/test/socket-rw-eagain.c +158 -0
- data/vendor/liburing/test/socket-rw-offset.c +157 -0
- data/vendor/liburing/test/socket-rw.c +145 -0
- data/vendor/liburing/test/splice.c +512 -0
- data/vendor/liburing/test/sq-full-cpp.cc +45 -0
- data/vendor/liburing/test/sq-full.c +45 -0
- data/vendor/liburing/test/sq-poll-dup.c +204 -0
- data/vendor/liburing/test/sq-poll-kthread.c +169 -0
- data/vendor/liburing/test/sq-poll-share.c +137 -0
- data/vendor/liburing/test/sq-space_left.c +159 -0
- data/vendor/liburing/test/sqpoll-cancel-hang.c +157 -0
- data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
- data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
- data/vendor/liburing/test/sqpoll-sleep.c +69 -0
- data/vendor/liburing/test/statx.c +172 -0
- data/vendor/liburing/test/stdout.c +232 -0
- data/vendor/liburing/test/submit-link-fail.c +154 -0
- data/vendor/liburing/test/submit-reuse.c +239 -0
- data/vendor/liburing/test/symlink.c +116 -0
- data/vendor/liburing/test/teardowns.c +58 -0
- data/vendor/liburing/test/thread-exit.c +143 -0
- data/vendor/liburing/test/timeout-new.c +252 -0
- data/vendor/liburing/test/timeout-overflow.c +204 -0
- data/vendor/liburing/test/timeout.c +1523 -0
- data/vendor/liburing/test/unlink.c +112 -0
- data/vendor/liburing/test/wakeup-hang.c +162 -0
- metadata +227 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b87dae4e2c17055e8206c820a4281774cdf3127195173948c97df4eb09a2bd13
|
4
|
+
data.tar.gz: 2e7bd958ec7435569423398069223eda41e9c2d89f580627bc22e9054276dd1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48f6489939da965463735c83acb4372263eb44b48b5a16da1e704a15e3af971a5d43abd7da5e44f2455b40d880413c6fa8159794e663176c83a11eddebdebc7d
|
7
|
+
data.tar.gz: 3ada5f9041041e91b6b2a7f31ec609352752317e87c51df090517c9e2b556d9ef69ef8842babd15f25b2257c4226431520ff15df505748cb38bb4a1d5a19063c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.86 2022-03-14
|
2
|
+
|
3
|
+
- Fix gemspec
|
4
|
+
|
5
|
+
## 0.85 2022-03-13
|
6
|
+
|
7
|
+
- Reduce write ops in `IO.gzip` (#77)
|
8
|
+
- Add support for read/write method detection for compression/decompression
|
9
|
+
methods (#77)
|
10
|
+
- Improve `Fiber#shutdown_all_children`
|
11
|
+
- Improve io_uring `wait_event` implementation (share single I/O poll across
|
12
|
+
multiple fibers)
|
13
|
+
- Fix io_uring `write` file offset
|
14
|
+
|
1
15
|
## 0.84 2022-03-11
|
2
16
|
|
3
17
|
- Implement `IO.tee` (#82)
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
module ::Kernel
|
7
|
+
def trace(*args)
|
8
|
+
STDOUT.orig_write(format_trace(args))
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_trace(args)
|
12
|
+
if args.first.is_a?(String)
|
13
|
+
if args.size > 1
|
14
|
+
format("%s: %p\n", args.shift, args)
|
15
|
+
else
|
16
|
+
format("%s\n", args.first)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def monotonic_clock
|
24
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
count = 10000
|
29
|
+
|
30
|
+
count.times do
|
31
|
+
spin { Polyphony.backend_wait_event(true) }
|
32
|
+
end
|
33
|
+
|
34
|
+
trace 'sleeping...'
|
35
|
+
sleep 1
|
36
|
+
|
37
|
+
trace 'shutting down children...'
|
38
|
+
Fiber.current.shutdown_all_children
|
39
|
+
trace 'done'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
module ::Kernel
|
7
|
+
def trace(*args)
|
8
|
+
STDOUT.orig_write(format_trace(args))
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_trace(args)
|
12
|
+
if args.first.is_a?(String)
|
13
|
+
if args.size > 1
|
14
|
+
format("%s: %p\n", args.shift, args)
|
15
|
+
else
|
16
|
+
format("%s\n", args.first)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def monotonic_clock
|
24
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
count = 10
|
29
|
+
|
30
|
+
f = spin do
|
31
|
+
count.times { spin { suspend } }
|
32
|
+
suspend
|
33
|
+
end
|
34
|
+
|
35
|
+
snooze
|
36
|
+
trace children_alive: f.children.size
|
37
|
+
|
38
|
+
trace 'shutting down children...'
|
39
|
+
f.shutdown_all_children
|
40
|
+
|
41
|
+
trace children_alive: f.children.size
|
data/examples/io/gzip.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
require 'polyphony'
|
7
|
+
|
8
|
+
def handle_echo_client(conn)
|
9
|
+
buffer = Polyphony.pipe
|
10
|
+
spin { buffer.splice_to_eof_from(conn) }
|
11
|
+
spin { conn.splice_to_eof_from(buffer) }
|
12
|
+
end
|
13
|
+
|
14
|
+
puts "Serving echo on port 1234..."
|
15
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_echo_client(c) }
|
@@ -41,8 +41,10 @@ typedef struct Backend_t {
|
|
41
41
|
op_context_store_t store;
|
42
42
|
unsigned int pending_sqes;
|
43
43
|
unsigned int prepared_limit;
|
44
|
-
int event_fd;
|
45
44
|
int ring_initialized;
|
45
|
+
|
46
|
+
int event_fd;
|
47
|
+
op_context_t *event_fd_ctx;
|
46
48
|
} Backend_t;
|
47
49
|
|
48
50
|
static void Backend_mark(void *ptr) {
|
@@ -83,6 +85,7 @@ static VALUE Backend_initialize(VALUE self) {
|
|
83
85
|
backend->pending_sqes = 0;
|
84
86
|
backend->ring_initialized = 0;
|
85
87
|
backend->event_fd = -1;
|
88
|
+
backend->event_fd_ctx = NULL;
|
86
89
|
|
87
90
|
context_store_initialize(&backend->store);
|
88
91
|
|
@@ -183,13 +186,21 @@ done:
|
|
183
186
|
return;
|
184
187
|
}
|
185
188
|
|
189
|
+
inline void io_uring_backend_immediate_submit(Backend_t *backend) {
|
190
|
+
backend->pending_sqes = 0;
|
191
|
+
io_uring_submit(&backend->ring);
|
192
|
+
}
|
193
|
+
|
194
|
+
inline void io_uring_backend_defer_submit(Backend_t *backend) {
|
195
|
+
backend->pending_sqes += 1;
|
196
|
+
if (backend->pending_sqes >= backend->prepared_limit)
|
197
|
+
io_uring_backend_immediate_submit(backend);
|
198
|
+
}
|
199
|
+
|
186
200
|
void io_uring_backend_poll(Backend_t *backend) {
|
187
201
|
poll_context_t poll_ctx;
|
188
202
|
poll_ctx.ring = &backend->ring;
|
189
|
-
if (backend->pending_sqes)
|
190
|
-
backend->pending_sqes = 0;
|
191
|
-
io_uring_submit(&backend->ring);
|
192
|
-
}
|
203
|
+
if (backend->pending_sqes) io_uring_backend_immediate_submit(backend);
|
193
204
|
|
194
205
|
wait_cqe:
|
195
206
|
backend->base.currently_polling = 1;
|
@@ -211,10 +222,7 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
211
222
|
|
212
223
|
backend->base.poll_count++;
|
213
224
|
|
214
|
-
if (!is_blocking && backend->pending_sqes)
|
215
|
-
backend->pending_sqes = 0;
|
216
|
-
io_uring_submit(&backend->ring);
|
217
|
-
}
|
225
|
+
if (!is_blocking && backend->pending_sqes) io_uring_backend_immediate_submit(backend);
|
218
226
|
|
219
227
|
COND_TRACE(&backend->base, 2, SYM_enter_poll, rb_fiber_current());
|
220
228
|
|
@@ -263,8 +271,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
263
271
|
// NOP which would cause the io_uring_enter syscall to return
|
264
272
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
265
273
|
io_uring_prep_nop(sqe);
|
266
|
-
backend
|
267
|
-
io_uring_submit(&backend->ring);
|
274
|
+
io_uring_backend_immediate_submit(backend);
|
268
275
|
|
269
276
|
return Qtrue;
|
270
277
|
}
|
@@ -272,14 +279,6 @@ VALUE Backend_wakeup(VALUE self) {
|
|
272
279
|
return Qnil;
|
273
280
|
}
|
274
281
|
|
275
|
-
inline void io_uring_backend_defer_submit(Backend_t *backend) {
|
276
|
-
backend->pending_sqes += 1;
|
277
|
-
if (backend->pending_sqes >= backend->prepared_limit) {
|
278
|
-
backend->pending_sqes = 0;
|
279
|
-
io_uring_submit(&backend->ring);
|
280
|
-
}
|
281
|
-
}
|
282
|
-
|
283
282
|
int io_uring_backend_defer_submit_and_await(
|
284
283
|
Backend_t *backend,
|
285
284
|
struct io_uring_sqe *sqe,
|
@@ -305,8 +304,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
305
304
|
ctx->result = -ECANCELED;
|
306
305
|
sqe = io_uring_get_sqe(&backend->ring);
|
307
306
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
308
|
-
backend
|
309
|
-
io_uring_submit(&backend->ring);
|
307
|
+
io_uring_backend_immediate_submit(backend);
|
310
308
|
}
|
311
309
|
|
312
310
|
if (value_ptr) (*value_ptr) = switchpoint_result;
|
@@ -552,7 +550,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
552
550
|
int result;
|
553
551
|
int completed;
|
554
552
|
|
555
|
-
io_uring_prep_write(sqe, fd, buffer.ptr, left,
|
553
|
+
io_uring_prep_write(sqe, fd, buffer.ptr, left, -1);
|
556
554
|
|
557
555
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
558
556
|
completed = context_store_release(&backend->store, ctx);
|
@@ -1161,8 +1159,7 @@ VALUE Backend_timeout_ensure(VALUE arg) {
|
|
1161
1159
|
// op was not completed, so we need to cancel it
|
1162
1160
|
sqe = io_uring_get_sqe(&timeout_ctx->backend->ring);
|
1163
1161
|
io_uring_prep_cancel(sqe, (__u64)timeout_ctx->ctx, 0);
|
1164
|
-
timeout_ctx->backend
|
1165
|
-
io_uring_submit(&timeout_ctx->backend->ring);
|
1162
|
+
io_uring_backend_immediate_submit(timeout_ctx->backend);
|
1166
1163
|
}
|
1167
1164
|
context_store_release(&timeout_ctx->backend->store, timeout_ctx->ctx);
|
1168
1165
|
return Qnil;
|
@@ -1237,6 +1234,13 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1237
1234
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
1238
1235
|
}
|
1239
1236
|
|
1237
|
+
/*
|
1238
|
+
Blocks a fiber indefinitely. This is accomplished by using an eventfd that will
|
1239
|
+
never be signalled. The eventfd is needed so we could do a blocking polling for
|
1240
|
+
completions even when no other I/O operations are pending.
|
1241
|
+
|
1242
|
+
The eventfd is refcounted in order to allow multiple fibers to be blocked.
|
1243
|
+
*/
|
1240
1244
|
VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
1241
1245
|
Backend_t *backend;
|
1242
1246
|
VALUE resume_value;
|
@@ -1251,7 +1255,32 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1251
1255
|
}
|
1252
1256
|
}
|
1253
1257
|
|
1254
|
-
|
1258
|
+
if (!backend->event_fd_ctx) {
|
1259
|
+
struct io_uring_sqe *sqe;
|
1260
|
+
|
1261
|
+
backend->event_fd_ctx = context_store_acquire(&backend->store, OP_POLL);
|
1262
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1263
|
+
io_uring_prep_poll_add(sqe, backend->event_fd, POLLIN);
|
1264
|
+
backend->base.op_count++;
|
1265
|
+
io_uring_sqe_set_data(sqe, backend->event_fd_ctx);
|
1266
|
+
io_uring_backend_defer_submit(backend);
|
1267
|
+
}
|
1268
|
+
else
|
1269
|
+
backend->event_fd_ctx->ref_count += 1;
|
1270
|
+
|
1271
|
+
resume_value = backend_await((struct Backend_base *)backend);
|
1272
|
+
context_store_release(&backend->store, backend->event_fd_ctx);
|
1273
|
+
|
1274
|
+
if (backend->event_fd_ctx->ref_count == 1) {
|
1275
|
+
|
1276
|
+
// last fiber to use the eventfd, so we cancel the ongoing poll
|
1277
|
+
struct io_uring_sqe *sqe;
|
1278
|
+
sqe = io_uring_get_sqe(&backend->ring);
|
1279
|
+
io_uring_prep_cancel(sqe, (__u64)backend->event_fd_ctx, 0);
|
1280
|
+
io_uring_backend_immediate_submit(backend);
|
1281
|
+
backend->event_fd_ctx = NULL;
|
1282
|
+
}
|
1283
|
+
|
1255
1284
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(resume_value);
|
1256
1285
|
RB_GC_GUARD(resume_value);
|
1257
1286
|
return resume_value;
|
@@ -1354,8 +1383,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1354
1383
|
ctx->result = -ECANCELED;
|
1355
1384
|
sqe = io_uring_get_sqe(&backend->ring);
|
1356
1385
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1357
|
-
backend
|
1358
|
-
io_uring_submit(&backend->ring);
|
1386
|
+
io_uring_backend_immediate_submit(backend);
|
1359
1387
|
}
|
1360
1388
|
else {
|
1361
1389
|
ctx->ref_count = 1;
|
@@ -1385,8 +1413,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1385
1413
|
ctx->result = -ECANCELED;
|
1386
1414
|
sqe = io_uring_get_sqe(&backend->ring);
|
1387
1415
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1388
|
-
backend
|
1389
|
-
io_uring_submit(&backend->ring);
|
1416
|
+
io_uring_backend_immediate_submit(backend);
|
1390
1417
|
RAISE_IF_EXCEPTION(resume_value);
|
1391
1418
|
return resume_value;
|
1392
1419
|
}
|
@@ -1452,8 +1479,7 @@ static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
|
|
1452
1479
|
ctx->result = -ECANCELED;
|
1453
1480
|
sqe = io_uring_get_sqe(&backend->ring);
|
1454
1481
|
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1455
|
-
backend
|
1456
|
-
io_uring_submit(&backend->ring);
|
1482
|
+
io_uring_backend_immediate_submit(backend);
|
1457
1483
|
}
|
1458
1484
|
|
1459
1485
|
static inline int splice_chunks_await_ops(
|
@@ -13,24 +13,68 @@
|
|
13
13
|
|
14
14
|
ID ID_at;
|
15
15
|
ID ID_read_method;
|
16
|
+
ID ID_readpartial;
|
16
17
|
ID ID_to_i;
|
17
18
|
ID ID_write_method;
|
19
|
+
ID ID_write;
|
18
20
|
|
21
|
+
VALUE SYM_backend_read;
|
22
|
+
VALUE SYM_backend_recv;
|
23
|
+
VALUE SYM_backend_send;
|
24
|
+
VALUE SYM_backend_write;
|
25
|
+
VALUE SYM_call;
|
26
|
+
VALUE SYM_comment;
|
19
27
|
VALUE SYM_mtime;
|
20
28
|
VALUE SYM_orig_name;
|
21
|
-
VALUE
|
29
|
+
VALUE SYM_readpartial;
|
22
30
|
|
23
31
|
enum read_method {
|
24
32
|
RM_BACKEND_READ,
|
25
|
-
RM_BACKEND_RECV
|
33
|
+
RM_BACKEND_RECV,
|
34
|
+
RM_READPARTIAL,
|
35
|
+
RM_CALL
|
26
36
|
};
|
27
37
|
|
28
38
|
enum write_method {
|
29
39
|
WM_BACKEND_WRITE,
|
30
|
-
WM_BACKEND_SEND
|
40
|
+
WM_BACKEND_SEND,
|
41
|
+
WM_WRITE,
|
42
|
+
WM_CALL
|
31
43
|
};
|
32
44
|
|
33
|
-
|
45
|
+
static enum read_method detect_read_method(VALUE io) {
|
46
|
+
if (rb_respond_to(io, ID_read_method)) {
|
47
|
+
VALUE method = rb_funcall(io, ID_read_method, 0);
|
48
|
+
if (method == SYM_readpartial) return RM_READPARTIAL;
|
49
|
+
if (method == SYM_backend_read) return RM_BACKEND_READ;
|
50
|
+
if (method == SYM_backend_recv) return RM_BACKEND_RECV;
|
51
|
+
if (method == SYM_call) return RM_CALL;
|
52
|
+
|
53
|
+
rb_raise(rb_eRuntimeError, "Given io instance uses unsupported read method");
|
54
|
+
}
|
55
|
+
else if (rb_respond_to(io, ID_call))
|
56
|
+
return RM_CALL;
|
57
|
+
else
|
58
|
+
rb_raise(rb_eRuntimeError, "Given io instance should be a callable or respond to #__read_method__");
|
59
|
+
}
|
60
|
+
|
61
|
+
static enum write_method detect_write_method(VALUE io) {
|
62
|
+
if (rb_respond_to(io, ID_write_method)) {
|
63
|
+
VALUE method = rb_funcall(io, ID_write_method, 0);
|
64
|
+
if (method == SYM_readpartial) return WM_WRITE;
|
65
|
+
if (method == SYM_backend_write) return WM_BACKEND_WRITE;
|
66
|
+
if (method == SYM_backend_send) return WM_BACKEND_SEND;
|
67
|
+
if (method == SYM_call) return WM_CALL;
|
68
|
+
|
69
|
+
rb_raise(rb_eRuntimeError, "Given io instance uses unsupported write method");
|
70
|
+
}
|
71
|
+
else if (rb_respond_to(io, ID_call))
|
72
|
+
return WM_CALL;
|
73
|
+
else
|
74
|
+
rb_raise(rb_eRuntimeError, "Given io instance should be a callable or respond to #__write_method__");
|
75
|
+
}
|
76
|
+
|
77
|
+
#define PRINT_BUFFER(prefix, ptr, len) { \
|
34
78
|
printf("%s buffer (%d): ", prefix, (int)len); \
|
35
79
|
for (int i = 0; i < len; i++) printf("%02X ", ptr[i]); \
|
36
80
|
printf("\n"); \
|
@@ -40,6 +84,7 @@ enum write_method {
|
|
40
84
|
#define MAX_WRITE_STR_LEN 16384
|
41
85
|
#define DEFAULT_LEVEL 9
|
42
86
|
#define DEFAULT_MEM_LEVEL 8
|
87
|
+
#define GZIP_FOOTER_LEN 8
|
43
88
|
|
44
89
|
/* from zutil.h */
|
45
90
|
#define OS_MSDOS 0x00
|
@@ -63,14 +108,64 @@ enum write_method {
|
|
63
108
|
#define OS_CODE OS_UNIX
|
64
109
|
#endif
|
65
110
|
|
111
|
+
|
66
112
|
static inline int read_to_raw_buffer(VALUE backend, VALUE io, enum read_method method, struct raw_buffer *buffer) {
|
67
|
-
|
68
|
-
|
113
|
+
switch (method) {
|
114
|
+
case RM_BACKEND_READ: {
|
115
|
+
VALUE len = Backend_read(backend, io, PTR2FIX(buffer), Qnil, Qfalse, INT2FIX(0));
|
116
|
+
return (len == Qnil) ? 0 : FIX2INT(len);
|
117
|
+
}
|
118
|
+
case RM_BACKEND_RECV: {
|
119
|
+
VALUE len = Backend_recv(backend, io, PTR2FIX(buffer), Qnil, INT2FIX(0));
|
120
|
+
return (len == Qnil) ? 0 : FIX2INT(len);
|
121
|
+
}
|
122
|
+
case RM_READPARTIAL: {
|
123
|
+
VALUE str = rb_funcall(io, ID_readpartial, 1, INT2FIX(buffer->len));
|
124
|
+
int len = RSTRING_LEN(str);
|
125
|
+
if (len) memcpy(buffer->ptr, RSTRING_PTR(str), len);
|
126
|
+
RB_GC_GUARD(str);
|
127
|
+
return len;
|
128
|
+
}
|
129
|
+
case RM_CALL: {
|
130
|
+
VALUE str = rb_funcall(io, ID_call, INT2FIX(buffer->len));
|
131
|
+
if (TYPE(str) != T_STRING)
|
132
|
+
rb_raise(rb_eRuntimeError, "io#call must return a string");
|
133
|
+
int len = RSTRING_LEN(str);
|
134
|
+
if (len > buffer->len) len = buffer->len;
|
135
|
+
if (len) memcpy(buffer->ptr, RSTRING_PTR(str), len);
|
136
|
+
RB_GC_GUARD(str);
|
137
|
+
return len;
|
138
|
+
}
|
139
|
+
}
|
69
140
|
}
|
70
141
|
|
71
142
|
static inline int write_from_raw_buffer(VALUE backend, VALUE io, enum write_method method, struct raw_buffer *buffer) {
|
72
|
-
|
73
|
-
|
143
|
+
switch (method) {
|
144
|
+
case WM_BACKEND_WRITE: {
|
145
|
+
VALUE len = Backend_write(backend, io, PTR2FIX(buffer));
|
146
|
+
return FIX2INT(len);
|
147
|
+
}
|
148
|
+
case WM_BACKEND_SEND: {
|
149
|
+
VALUE len = Backend_send(backend, io, PTR2FIX(buffer), INT2FIX(0));
|
150
|
+
return FIX2INT(len);
|
151
|
+
}
|
152
|
+
case WM_WRITE: {
|
153
|
+
VALUE str = rb_str_new(0, buffer->len);
|
154
|
+
memcpy(RSTRING_PTR(str), buffer->ptr, buffer->len);
|
155
|
+
rb_str_modify_expand(str, buffer->len);
|
156
|
+
rb_funcall(io, ID_write, 1, str);
|
157
|
+
RB_GC_GUARD(str);
|
158
|
+
return buffer->len;
|
159
|
+
}
|
160
|
+
case WM_CALL: {
|
161
|
+
VALUE str = rb_str_new(0, buffer->len);
|
162
|
+
memcpy(RSTRING_PTR(str), buffer->ptr, buffer->len);
|
163
|
+
rb_str_modify_expand(str, buffer->len);
|
164
|
+
rb_funcall(io, ID_call, 1, str);
|
165
|
+
RB_GC_GUARD(str);
|
166
|
+
return buffer->len;
|
167
|
+
}
|
168
|
+
}
|
74
169
|
}
|
75
170
|
|
76
171
|
static inline int write_c_string_from_str(VALUE str, struct raw_buffer *buffer) {
|
@@ -165,12 +260,12 @@ int gzip_prepare_header(struct gzip_header_ctx *ctx, char *buffer, int maxlen) {
|
|
165
260
|
}
|
166
261
|
|
167
262
|
int gzip_prepare_footer(unsigned long crc32, unsigned long total_in, char *buffer, int maxlen) {
|
168
|
-
assert(maxlen >=
|
263
|
+
assert(maxlen >= GZIP_FOOTER_LEN);
|
169
264
|
|
170
265
|
gzfile_set32(crc32, buffer);
|
171
266
|
gzfile_set32(total_in, buffer + 4);
|
172
267
|
|
173
|
-
return
|
268
|
+
return GZIP_FOOTER_LEN;
|
174
269
|
}
|
175
270
|
|
176
271
|
enum stream_mode {
|
@@ -183,7 +278,11 @@ struct z_stream_ctx {
|
|
183
278
|
VALUE src;
|
184
279
|
VALUE dest;
|
185
280
|
|
281
|
+
enum read_method src_read_method;
|
282
|
+
enum write_method dest_write_method;
|
283
|
+
|
186
284
|
enum stream_mode mode;
|
285
|
+
int f_gzip_footer; // should a gzip footer be generated
|
187
286
|
z_stream strm;
|
188
287
|
|
189
288
|
unsigned char in[CHUNK];
|
@@ -216,11 +315,11 @@ void gzip_read_header(struct z_stream_ctx *ctx, struct gzip_header_ctx *header_c
|
|
216
315
|
int flags;
|
217
316
|
|
218
317
|
while (ctx->in_total < 10) {
|
219
|
-
int read = read_to_raw_buffer(ctx->backend, ctx->src,
|
318
|
+
int read = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
|
220
319
|
if (read == 0) goto error;
|
221
320
|
ctx->in_total += read;
|
222
321
|
}
|
223
|
-
//
|
322
|
+
// PRINT_BUFFER("read gzip header", ctx->in, ctx->in_total);
|
224
323
|
if (ctx->in[0] != GZ_MAGIC1) goto error;
|
225
324
|
if (ctx->in[1] != GZ_MAGIC2) goto error;
|
226
325
|
if (ctx->in[2] != GZ_METHOD_DEFLATE) goto error;
|
@@ -245,9 +344,6 @@ error:
|
|
245
344
|
rb_raise(rb_eRuntimeError, "Invalid gzip header");
|
246
345
|
}
|
247
346
|
|
248
|
-
// void gzip_read_footer(struct z_stream_ctx *ctx, struct gzip_footer_ctx *footer_ctx) {
|
249
|
-
// }
|
250
|
-
|
251
347
|
static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, int eof) {
|
252
348
|
int ret;
|
253
349
|
int written;
|
@@ -260,8 +356,14 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in
|
|
260
356
|
written = avail_out_pre - ctx->strm.avail_out;
|
261
357
|
out_buffer.ptr = ctx->out;
|
262
358
|
out_buffer.len = ctx->out_pos + written;
|
359
|
+
|
360
|
+
if (eof && ctx->f_gzip_footer && (CHUNK - out_buffer.len >= GZIP_FOOTER_LEN)) {
|
361
|
+
gzip_prepare_footer(ctx->crc32, ctx->in_total, out_buffer.ptr + out_buffer.len, 8);
|
362
|
+
out_buffer.len += GZIP_FOOTER_LEN;
|
363
|
+
}
|
364
|
+
|
263
365
|
if (out_buffer.len) {
|
264
|
-
ret = write_from_raw_buffer(ctx->backend, ctx->dest,
|
366
|
+
ret = write_from_raw_buffer(ctx->backend, ctx->dest, ctx->dest_write_method, &out_buffer);
|
265
367
|
if (ctx->mode == SM_INFLATE)
|
266
368
|
ctx->crc32 = crc32(ctx->crc32, out_buffer.ptr + ctx->out_pos, written);
|
267
369
|
ctx->out_total += ret - ctx->out_pos;
|
@@ -271,7 +373,7 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in
|
|
271
373
|
}
|
272
374
|
|
273
375
|
void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
274
|
-
zlib_func fun = (ctx->mode == SM_DEFLATE) ? deflate : inflate;
|
376
|
+
zlib_func fun = (ctx->mode == SM_DEFLATE) ? deflate : inflate;
|
275
377
|
|
276
378
|
if (ctx->in_total > ctx->in_pos) {
|
277
379
|
// In bytes already read for parsing gzip header, so we need to process the
|
@@ -289,7 +391,7 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
|
289
391
|
while (1) {
|
290
392
|
struct raw_buffer in_buffer = {ctx->in, CHUNK};
|
291
393
|
ctx->strm.next_in = ctx->in;
|
292
|
-
int read_len = ctx->strm.avail_in = read_to_raw_buffer(ctx->backend, ctx->src,
|
394
|
+
int read_len = ctx->strm.avail_in = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
|
293
395
|
if (!read_len) break;
|
294
396
|
int eof = read_len < CHUNK;
|
295
397
|
|
@@ -297,7 +399,7 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) {
|
|
297
399
|
ctx->crc32 = crc32(ctx->crc32, ctx->in, read_len);
|
298
400
|
ctx->in_total += read_len;
|
299
401
|
|
300
|
-
//
|
402
|
+
// PRINT_BUFFER("read stream", ctx->in, read_len);
|
301
403
|
|
302
404
|
while (1) {
|
303
405
|
// z_stream_write_out returns strm.avail_out. If there's still room in the
|
@@ -318,7 +420,10 @@ static inline void setup_ctx(struct z_stream_ctx *ctx, enum stream_mode mode, VA
|
|
318
420
|
ctx->backend = BACKEND();
|
319
421
|
ctx->src = src;
|
320
422
|
ctx->dest = dest;
|
423
|
+
ctx->src_read_method = detect_read_method(src);
|
424
|
+
ctx->dest_write_method = detect_write_method(dest);
|
321
425
|
ctx->mode = mode;
|
426
|
+
ctx->f_gzip_footer = 0;
|
322
427
|
ctx->strm.zalloc = Z_NULL;
|
323
428
|
ctx->strm.zfree = Z_NULL;
|
324
429
|
ctx->strm.opaque = Z_NULL;
|
@@ -349,14 +454,12 @@ VALUE IO_gzip(int argc, VALUE *argv, VALUE self) {
|
|
349
454
|
int ret;
|
350
455
|
|
351
456
|
setup_ctx(&ctx, SM_DEFLATE, src, dest);
|
457
|
+
ctx.f_gzip_footer = 1; // write gzip footer
|
352
458
|
ctx.out_pos = gzip_prepare_header(&header_ctx, ctx.out, sizeof(ctx.out));
|
353
459
|
|
354
460
|
ret = deflateInit2(&ctx.strm, level, Z_DEFLATED, -MAX_WBITS, DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
355
461
|
if (ret != Z_OK) return INT2FIX(ret);
|
356
462
|
z_stream_io_loop(&ctx);
|
357
|
-
int footer_len = gzip_prepare_footer(ctx.crc32, ctx.in_total, ctx.out, sizeof(ctx.out));
|
358
|
-
struct raw_buffer footer_buffer = {ctx.out, footer_len};
|
359
|
-
write_from_raw_buffer(ctx.backend, dest, WM_BACKEND_WRITE, &footer_buffer);
|
360
463
|
deflateEnd(&ctx.strm);
|
361
464
|
|
362
465
|
return INT2FIX(ctx.out_total);
|
@@ -431,10 +534,18 @@ void Init_IOExtensions() {
|
|
431
534
|
|
432
535
|
ID_at = rb_intern("at");
|
433
536
|
ID_read_method = rb_intern("__read_method__");
|
537
|
+
ID_readpartial = rb_intern("readpartial");
|
434
538
|
ID_to_i = rb_intern("to_i");
|
435
539
|
ID_write_method = rb_intern("__write_method__");
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
540
|
+
ID_write = rb_intern("write");
|
541
|
+
|
542
|
+
SYM_backend_read = ID2SYM(rb_intern("backend_read"));
|
543
|
+
SYM_backend_recv = ID2SYM(rb_intern("backend_recv"));
|
544
|
+
SYM_backend_send = ID2SYM(rb_intern("backend_send"));
|
545
|
+
SYM_backend_write = ID2SYM(rb_intern("backend_write"));
|
546
|
+
SYM_call = ID2SYM(rb_intern("call"));
|
547
|
+
SYM_comment = ID2SYM(rb_intern("comment"));
|
548
|
+
SYM_mtime = ID2SYM(rb_intern("mtime"));
|
549
|
+
SYM_orig_name = ID2SYM(rb_intern("orig_name"));
|
550
|
+
SYM_readpartial = ID2SYM(rb_intern("readpartial"));
|
440
551
|
}
|
@@ -390,12 +390,14 @@ module Polyphony
|
|
390
390
|
def shutdown_all_children(graceful = false)
|
391
391
|
return self unless @children
|
392
392
|
|
393
|
+
pending = []
|
393
394
|
@children.keys.each do |c|
|
394
395
|
next if c.dead?
|
395
396
|
|
396
397
|
c.terminate(graceful)
|
397
|
-
c
|
398
|
+
pending << c
|
398
399
|
end
|
400
|
+
Fiber.await(*pending)
|
399
401
|
self
|
400
402
|
end
|
401
403
|
|