polyphony 1.3 → 1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +14 -0
- data/README.md +11 -45
- data/TODO.md +5 -10
- data/docs/installation.md +30 -0
- data/docs/readme.md +11 -45
- data/examples/core/stages.rb +99 -0
- data/examples/pipes/http_server.rb +42 -12
- data/examples/pipes/http_server2.rb +45 -0
- data/ext/polyphony/backend_common.c +1 -1
- data/ext/polyphony/backend_common.h +5 -0
- data/ext/polyphony/backend_io_uring.c +163 -144
- data/ext/polyphony/backend_libev.c +68 -15
- data/ext/polyphony/extconf.rb +6 -2
- data/ext/polyphony/pipe.c +1 -1
- data/ext/polyphony/polyphony.c +22 -25
- data/ext/polyphony/polyphony.h +1 -6
- data/ext/polyphony/win_uio.h +18 -0
- data/lib/polyphony/core/debug.rb +8 -8
- data/lib/polyphony/extensions/io.rb +17 -4
- data/lib/polyphony/extensions/kernel.rb +16 -0
- data/lib/polyphony/extensions/openssl.rb +11 -11
- data/lib/polyphony/extensions/pipe.rb +5 -5
- data/lib/polyphony/extensions/socket.rb +18 -32
- data/lib/polyphony/extensions/timeout.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/test/stress.rb +6 -1
- data/test/test_backend.rb +11 -2
- data/test/test_ext.rb +14 -0
- data/test/test_global_api.rb +5 -5
- data/test/test_io.rb +1 -1
- data/test/test_signal.rb +15 -6
- data/test/test_socket.rb +3 -102
- data/test/test_timer.rb +1 -1
- metadata +10 -6
@@ -42,21 +42,24 @@ thread.
|
|
42
42
|
#define _GNU_SOURCE 1
|
43
43
|
#endif
|
44
44
|
|
45
|
-
#include <netdb.h>
|
46
|
-
#include <sys/socket.h>
|
47
|
-
#include <sys/uio.h>
|
48
45
|
#include <unistd.h>
|
49
|
-
#include <netinet/in.h>
|
50
|
-
#include <arpa/inet.h>
|
51
46
|
#include <stdnoreturn.h>
|
52
47
|
#include <sys/types.h>
|
48
|
+
|
49
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
53
50
|
#include <sys/wait.h>
|
51
|
+
#endif
|
52
|
+
|
54
53
|
#include <fcntl.h>
|
55
54
|
|
56
55
|
#include "polyphony.h"
|
57
56
|
#include "../libev/ev.h"
|
58
57
|
#include "ruby/io.h"
|
59
58
|
|
59
|
+
#ifndef POLYPHONY_WINDOWS
|
60
|
+
#include <sys/uio.h>
|
61
|
+
#endif
|
62
|
+
|
60
63
|
#include "../libev/ev.h"
|
61
64
|
#include "backend_common.h"
|
62
65
|
|
@@ -267,21 +270,25 @@ VALUE libev_wait_fd(Backend_t *backend, int fd, int events, int raise_exception)
|
|
267
270
|
}
|
268
271
|
|
269
272
|
static inline int fd_from_io(VALUE io, rb_io_t **fptr, int write_mode, int rectify_file_pos) {
|
273
|
+
if (TYPE(io) == T_FIXNUM) {
|
274
|
+
*fptr = NULL;
|
275
|
+
return FIX2INT(io);
|
276
|
+
}
|
277
|
+
|
270
278
|
if (rb_obj_class(io) == cPipe) {
|
271
279
|
*fptr = NULL;
|
272
280
|
Pipe_verify_blocking_mode(io, Qfalse);
|
273
281
|
return Pipe_get_fd(io, write_mode);
|
274
282
|
}
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
}
|
283
|
+
|
284
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
285
|
+
if (underlying_io != Qnil) io = underlying_io;
|
286
|
+
|
287
|
+
GetOpenFile(io, *fptr);
|
288
|
+
int fd = rb_io_descriptor(io);
|
289
|
+
io_verify_blocking_mode(io, fd, Qfalse);
|
290
|
+
if (rectify_file_pos) rectify_io_file_pos(*fptr);
|
291
|
+
return fd;
|
285
292
|
}
|
286
293
|
|
287
294
|
VALUE Backend_read(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE to_eof, VALUE pos) {
|
@@ -558,6 +565,7 @@ error:
|
|
558
565
|
return RAISE_EXCEPTION(switchpoint_result);
|
559
566
|
}
|
560
567
|
|
568
|
+
#ifndef POLYPHONY_WINDOWS
|
561
569
|
VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
562
570
|
Backend_t *backend;
|
563
571
|
struct libev_io watcher;
|
@@ -629,15 +637,23 @@ error:
|
|
629
637
|
free(iov);
|
630
638
|
return RAISE_EXCEPTION(switchpoint_result);
|
631
639
|
}
|
640
|
+
#endif
|
632
641
|
|
633
642
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
634
643
|
if (argc < 2)
|
635
644
|
// TODO: raise ArgumentError
|
636
645
|
rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
|
637
646
|
|
647
|
+
#ifdef POLYPHONY_WINDOWS
|
648
|
+
int total = 0;
|
649
|
+
for (int i = 1; i < argc; i++)
|
650
|
+
total += FIX2INT(Backend_write(self, argv[0], argv[i]));
|
651
|
+
return INT2FIX(total);
|
652
|
+
#else
|
638
653
|
return (argc == 2) ?
|
639
654
|
Backend_write(self, argv[0], argv[1]) :
|
640
655
|
Backend_writev(self, argv[0], argc - 1, argv + 1);
|
656
|
+
#endif
|
641
657
|
}
|
642
658
|
|
643
659
|
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
@@ -1135,6 +1151,31 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
1135
1151
|
return libev_wait_fd(backend, fd, events, 1);
|
1136
1152
|
}
|
1137
1153
|
|
1154
|
+
VALUE Backend_close(VALUE self, VALUE io) {
|
1155
|
+
Backend_t *backend;
|
1156
|
+
rb_io_t *fptr;
|
1157
|
+
VALUE resume_value = Qnil;
|
1158
|
+
int result;
|
1159
|
+
int fd = fd_from_io(io, &fptr, 0, 0);
|
1160
|
+
if (fd < 0) return Qnil;
|
1161
|
+
|
1162
|
+
GetBackend(self, backend);
|
1163
|
+
|
1164
|
+
result = close(fd);
|
1165
|
+
if (result == -1) {
|
1166
|
+
int err = errno;
|
1167
|
+
rb_syserr_fail(err, strerror(err));
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
resume_value = backend_snooze(&backend->base);
|
1171
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1172
|
+
RB_GC_GUARD(resume_value);
|
1173
|
+
|
1174
|
+
if (fptr) fptr_finalize(fptr);
|
1175
|
+
// fd = -1;
|
1176
|
+
return io;
|
1177
|
+
}
|
1178
|
+
|
1138
1179
|
struct libev_timer {
|
1139
1180
|
struct ev_timer timer;
|
1140
1181
|
VALUE fiber;
|
@@ -1292,6 +1333,7 @@ struct libev_child {
|
|
1292
1333
|
VALUE fiber;
|
1293
1334
|
};
|
1294
1335
|
|
1336
|
+
#ifndef POLYPHONY_WINDOWS
|
1295
1337
|
void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
1296
1338
|
struct libev_child *watcher = (struct libev_child *)w;
|
1297
1339
|
int exit_status = WEXITSTATUS(w->rstatus);
|
@@ -1300,8 +1342,12 @@ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
|
1300
1342
|
status = rb_ary_new_from_args(2, INT2FIX(w->rpid), INT2FIX(exit_status));
|
1301
1343
|
Fiber_make_runnable(watcher->fiber, status);
|
1302
1344
|
}
|
1345
|
+
#endif
|
1303
1346
|
|
1304
1347
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1348
|
+
#ifdef POLYPHONY_WINDOWS
|
1349
|
+
rb_raise(rb_eStandardError, "Not implemented");
|
1350
|
+
#else
|
1305
1351
|
Backend_t *backend;
|
1306
1352
|
struct libev_child watcher;
|
1307
1353
|
VALUE switchpoint_result = Qnil;
|
@@ -1319,6 +1365,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1319
1365
|
RB_GC_GUARD(watcher.fiber);
|
1320
1366
|
RB_GC_GUARD(switchpoint_result);
|
1321
1367
|
return switchpoint_result;
|
1368
|
+
#endif
|
1322
1369
|
}
|
1323
1370
|
#endif
|
1324
1371
|
|
@@ -1472,6 +1519,7 @@ done:
|
|
1472
1519
|
#endif
|
1473
1520
|
}
|
1474
1521
|
|
1522
|
+
#ifdef POLYPHONY_LINUX
|
1475
1523
|
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1476
1524
|
Backend_t *backend;
|
1477
1525
|
GetBackend(self, backend);
|
@@ -1561,6 +1609,7 @@ error:
|
|
1561
1609
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1562
1610
|
return RAISE_EXCEPTION(result);
|
1563
1611
|
}
|
1612
|
+
#endif
|
1564
1613
|
|
1565
1614
|
VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
|
1566
1615
|
Backend_t *backend;
|
@@ -1626,7 +1675,10 @@ void Init_Backend(void) {
|
|
1626
1675
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1627
1676
|
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1628
1677
|
rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
|
1678
|
+
|
1679
|
+
#ifdef POLYPHONY_LINUX
|
1629
1680
|
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1681
|
+
#endif
|
1630
1682
|
|
1631
1683
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1632
1684
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
@@ -1654,6 +1706,7 @@ void Init_Backend(void) {
|
|
1654
1706
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1655
1707
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1656
1708
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1709
|
+
rb_define_method(cBackend, "close", Backend_close, 1);
|
1657
1710
|
|
1658
1711
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
1659
1712
|
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'mkmf'
|
5
|
+
require 'rbconfig'
|
5
6
|
|
6
7
|
dir_config 'polyphony_ext'
|
7
8
|
|
8
9
|
KERNEL_INFO_RE = /Linux (\d)\.(\d+)(?:\.)?((?:\d+\.?)*)(?:\-)?([\w\-]+)?/
|
9
10
|
def get_config
|
10
11
|
config = { linux: !!(RUBY_PLATFORM =~ /linux/) }
|
12
|
+
config[:windows] = !!(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
11
13
|
return config if !config[:linux]
|
12
14
|
|
13
15
|
kernel_info = `uname -sr`
|
@@ -17,7 +19,8 @@ def get_config
|
|
17
19
|
version, major_revision, distribution = m[1].to_i, m[2].to_i, m[4]
|
18
20
|
|
19
21
|
combined_version = version.to_i * 100 + major_revision.to_i
|
20
|
-
|
22
|
+
|
23
|
+
config[:kernel_version] = combined_version
|
21
24
|
config[:pidfd_open] = combined_version > 503
|
22
25
|
config[:multishot_recv] = combined_version >= 600
|
23
26
|
config[:multishot_recvmsg] = combined_version >= 600
|
@@ -31,7 +34,7 @@ def get_config
|
|
31
34
|
end
|
32
35
|
|
33
36
|
config = get_config
|
34
|
-
puts "Building Polyphony
|
37
|
+
puts "Building Polyphony (\n#{config.map { |(k, v)| " #{k}: #{v}\n"}.join})"
|
35
38
|
|
36
39
|
require_relative 'zlib_conf'
|
37
40
|
|
@@ -71,6 +74,7 @@ if config[:io_uring]
|
|
71
74
|
else
|
72
75
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
73
76
|
$defs << "-DPOLYPHONY_LINUX" if config[:linux]
|
77
|
+
$defs << "-DPOLYPHONY_WINDOWS" if config[:windows]
|
74
78
|
|
75
79
|
$defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
|
76
80
|
|
data/ext/polyphony/pipe.c
CHANGED
@@ -97,8 +97,8 @@ VALUE Pipe_close(VALUE self) {
|
|
97
97
|
if (pipe->w_closed)
|
98
98
|
rb_raise(rb_eRuntimeError, "Pipe is already closed for writing");
|
99
99
|
|
100
|
+
Backend_close(BACKEND(), INT2FIX(pipe->fds[1]));
|
100
101
|
pipe->w_closed = 1;
|
101
|
-
close(pipe->fds[1]);
|
102
102
|
return self;
|
103
103
|
}
|
104
104
|
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -80,20 +80,6 @@ VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socke
|
|
80
80
|
return Backend_accept_loop(BACKEND(), server_socket, socket_class);
|
81
81
|
}
|
82
82
|
|
83
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
84
|
-
/* Starts a multishot accept operation on the given server socket. This API is
|
85
|
-
* available only for the io_uring backend.
|
86
|
-
*
|
87
|
-
* @param server_socket [Socket] socket to accept on
|
88
|
-
* @return [any] block return value
|
89
|
-
*/
|
90
|
-
|
91
|
-
VALUE Polyphony_backend_multishot_accept(VALUE self, VALUE server_socket) {
|
92
|
-
return Backend_multishot_accept(BACKEND(), server_socket);
|
93
|
-
}
|
94
|
-
#endif
|
95
|
-
|
96
|
-
|
97
83
|
/* Connects the given socket to the given address and port.
|
98
84
|
*
|
99
85
|
* @param io [Socket] socket to connect
|
@@ -404,9 +390,26 @@ VALUE Polyphony_raw_buffer_size(VALUE self, VALUE buffer) {
|
|
404
390
|
return INT2FIX(buffer_spec->len);
|
405
391
|
}
|
406
392
|
|
407
|
-
|
408
|
-
|
409
|
-
|
393
|
+
/* Closes the given IO.
|
394
|
+
*
|
395
|
+
* @param io [IO, Polyphony::Pipe] IO instance
|
396
|
+
* @return [IO, Polyphony::Pipe] given IO
|
397
|
+
*/
|
398
|
+
|
399
|
+
VALUE Polyphony_backend_close(VALUE self, VALUE io) {
|
400
|
+
return Backend_close(BACKEND(), io);
|
401
|
+
}
|
402
|
+
|
403
|
+
/* Ensures the given IO is in blocking/non-blocking mode.
|
404
|
+
*
|
405
|
+
* @param io [IO, Polyphony::Pipe] IO instance
|
406
|
+
* @param blocking [boolean] true for blocking, false for non-blocking mode
|
407
|
+
* @return [IO, Polyphony::Pipe] given IO
|
408
|
+
*/
|
409
|
+
|
410
|
+
VALUE Polyphony_backend_verify_blocking_mode(VALUE self, VALUE io, VALUE blocking) {
|
411
|
+
return Backend_verify_blocking_mode(BACKEND(), io, blocking);
|
412
|
+
}
|
410
413
|
|
411
414
|
void Init_Polyphony(void) {
|
412
415
|
mPolyphony = rb_define_module("Polyphony");
|
@@ -416,12 +419,6 @@ void Init_Polyphony(void) {
|
|
416
419
|
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
417
420
|
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
418
421
|
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
419
|
-
|
420
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
421
|
-
rb_define_singleton_method(mPolyphony, "backend_multishot_accept", Polyphony_backend_multishot_accept, 1);
|
422
|
-
#endif
|
423
|
-
|
424
|
-
|
425
422
|
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
|
426
423
|
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
|
427
424
|
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
|
@@ -448,8 +445,8 @@ void Init_Polyphony(void) {
|
|
448
445
|
rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
|
449
446
|
rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
|
450
447
|
rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
|
451
|
-
|
452
|
-
rb_define_singleton_method(mPolyphony, "backend_verify_blocking_mode",
|
448
|
+
rb_define_singleton_method(mPolyphony, "backend_close", Polyphony_backend_close, 1);
|
449
|
+
rb_define_singleton_method(mPolyphony, "backend_verify_blocking_mode", Polyphony_backend_verify_blocking_mode, 2);
|
453
450
|
|
454
451
|
rb_define_singleton_method(mPolyphony, "__with_raw_buffer__", Polyphony_with_raw_buffer, 1);
|
455
452
|
rb_define_singleton_method(mPolyphony, "__raw_buffer_get__", Polyphony_raw_buffer_get, -1);
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -101,11 +101,6 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
101
101
|
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
102
102
|
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
103
103
|
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
104
|
-
|
105
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
106
|
-
VALUE Backend_multishot_accept(VALUE self, VALUE io);
|
107
|
-
#endif
|
108
|
-
|
109
104
|
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
|
110
105
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
|
111
106
|
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
|
@@ -133,7 +128,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
|
|
133
128
|
VALUE Backend_waitpid(VALUE self, VALUE pid);
|
134
129
|
VALUE Backend_write(VALUE self, VALUE io, VALUE str);
|
135
130
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
|
136
|
-
|
131
|
+
VALUE Backend_close(VALUE self, VALUE io);
|
137
132
|
|
138
133
|
VALUE Backend_poll(VALUE self, VALUE blocking);
|
139
134
|
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// source: https://stackoverflow.com/questions/57897314/fatal-error-when-compiling-include-sys-uio-h-on-project-windows
|
2
|
+
|
3
|
+
#ifndef SYS_UIO_H
|
4
|
+
#define SYS_UIO_H
|
5
|
+
|
6
|
+
#include <inttypes.h>
|
7
|
+
#include <unistd.h>
|
8
|
+
|
9
|
+
struct iovec
|
10
|
+
{
|
11
|
+
void *iov_base; /* Base address of a memory region for input or output */
|
12
|
+
size_t iov_len; /* The size of the memory pointed to by iov_base */
|
13
|
+
};
|
14
|
+
|
15
|
+
ssize_t readv(int fildes, const struct iovec *iov, int iovcnt);
|
16
|
+
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
|
17
|
+
|
18
|
+
#endif /* SYS_UIO_H */
|
data/lib/polyphony/core/debug.rb
CHANGED
@@ -52,7 +52,7 @@ module Polyphony
|
|
52
52
|
|
53
53
|
# Converts an event (expressed as an array) to a hash.
|
54
54
|
#
|
55
|
-
# @param
|
55
|
+
# @param event [Array] event as emitted by the backend
|
56
56
|
# @return [Hash] event hash
|
57
57
|
def trace_event_info(event)
|
58
58
|
{
|
@@ -65,7 +65,7 @@ module Polyphony
|
|
65
65
|
|
66
66
|
# Returns an event hash for a `:block` event.
|
67
67
|
#
|
68
|
-
# @param
|
68
|
+
# @param event [Array] event array
|
69
69
|
# @return [Hash] event hash
|
70
70
|
def event_props_block(event)
|
71
71
|
{
|
@@ -76,7 +76,7 @@ module Polyphony
|
|
76
76
|
|
77
77
|
# Returns an event hash for a `:enter_poll` event.
|
78
78
|
#
|
79
|
-
# @param
|
79
|
+
# @param _event [Array] event array
|
80
80
|
# @return [Hash] event hash
|
81
81
|
def event_props_enter_poll(_event)
|
82
82
|
{}
|
@@ -84,7 +84,7 @@ module Polyphony
|
|
84
84
|
|
85
85
|
# Returns an event hash for a `:leave_poll` event.
|
86
86
|
#
|
87
|
-
# @param
|
87
|
+
# @param _event [Array] event array
|
88
88
|
# @return [Hash] event hash
|
89
89
|
def event_props_leave_poll(_event)
|
90
90
|
{}
|
@@ -92,7 +92,7 @@ module Polyphony
|
|
92
92
|
|
93
93
|
# Returns an event hash for a `:schedule` event.
|
94
94
|
#
|
95
|
-
# @param
|
95
|
+
# @param event [Array] event array
|
96
96
|
# @return [Hash] event hash
|
97
97
|
def event_props_schedule(event)
|
98
98
|
{
|
@@ -105,7 +105,7 @@ module Polyphony
|
|
105
105
|
|
106
106
|
# Returns an event hash for a `:spin` event.
|
107
107
|
#
|
108
|
-
# @param
|
108
|
+
# @param event [Array] event array
|
109
109
|
# @return [Hash] event hash
|
110
110
|
def event_props_spin(event)
|
111
111
|
{
|
@@ -117,7 +117,7 @@ module Polyphony
|
|
117
117
|
|
118
118
|
# Returns an event hash for a `:terminate` event.
|
119
119
|
#
|
120
|
-
# @param
|
120
|
+
# @param event [Array] event array
|
121
121
|
# @return [Hash] event hash
|
122
122
|
def event_props_terminate(event)
|
123
123
|
{
|
@@ -128,7 +128,7 @@ module Polyphony
|
|
128
128
|
|
129
129
|
# Returns an event hash for a `:unblock` event.
|
130
130
|
#
|
131
|
-
# @param
|
131
|
+
# @param event [Array] event array
|
132
132
|
# @return [Hash] event hash
|
133
133
|
def event_props_unblock(event)
|
134
134
|
{
|
@@ -197,7 +197,7 @@ class ::IO
|
|
197
197
|
alias_method :orig_read, :read
|
198
198
|
|
199
199
|
# @!visibility private
|
200
|
-
def read(len = nil, buf = nil, buffer_pos
|
200
|
+
def read(len = nil, buf = nil, buffer_pos = 0)
|
201
201
|
return '' if len == 0
|
202
202
|
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
203
203
|
|
@@ -214,7 +214,7 @@ class ::IO
|
|
214
214
|
alias_method :orig_readpartial, :read
|
215
215
|
|
216
216
|
# @!visibility private
|
217
|
-
def readpartial(len, str = +'', buffer_pos
|
217
|
+
def readpartial(len, str = +'', buffer_pos = 0, raise_on_eof = true)
|
218
218
|
result = Polyphony.backend_read(self, str, len, false, buffer_pos)
|
219
219
|
raise EOFError if !result && raise_on_eof
|
220
220
|
|
@@ -255,7 +255,7 @@ class ::IO
|
|
255
255
|
idx = @read_buffer.index(sep)
|
256
256
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
257
257
|
|
258
|
-
result = readpartial(8192, @read_buffer,
|
258
|
+
result = readpartial(8192, @read_buffer, -1)
|
259
259
|
return nil unless result
|
260
260
|
end
|
261
261
|
rescue EOFError
|
@@ -280,7 +280,7 @@ class ::IO
|
|
280
280
|
yield line
|
281
281
|
end
|
282
282
|
|
283
|
-
result = readpartial(8192, @read_buffer,
|
283
|
+
result = readpartial(8192, @read_buffer, -1)
|
284
284
|
return self if !result
|
285
285
|
end
|
286
286
|
rescue EOFError
|
@@ -427,6 +427,19 @@ class ::IO
|
|
427
427
|
Polyphony.backend_splice(src, self, maxlen)
|
428
428
|
end
|
429
429
|
|
430
|
+
# @!visibility private
|
431
|
+
alias_method :orig_close, :close
|
432
|
+
|
433
|
+
# Closes the IO instance
|
434
|
+
#
|
435
|
+
# @return [void]
|
436
|
+
def close
|
437
|
+
return if closed?
|
438
|
+
|
439
|
+
Polyphony.backend_close(self)
|
440
|
+
nil
|
441
|
+
end
|
442
|
+
|
430
443
|
if RUBY_PLATFORM =~ /linux/
|
431
444
|
# Tees data from the given IO.
|
432
445
|
#
|
@@ -5,6 +5,22 @@ require 'open3'
|
|
5
5
|
module Polyphony
|
6
6
|
# Intercepts calls to #trap
|
7
7
|
module TrapInterceptor
|
8
|
+
# Installs a signal handler. If a block is given (or the command parameter
|
9
|
+
# is a Proc or a callable), it is executed inside an out-of-band,
|
10
|
+
# prioritized fiber.
|
11
|
+
#
|
12
|
+
# If the command is the string “IGNORE” or “SIG_IGN”, the signal will be
|
13
|
+
# ignored. If the command is “DEFAULT” or “SIG_DFL”, the Ruby’s default
|
14
|
+
# handler will be invoked. If the command is “EXIT”, the script will be
|
15
|
+
# terminated by the signal. If the command is “SYSTEM_DEFAULT”, the
|
16
|
+
# operating system’s default handler will be invoked. Otherwise, the given
|
17
|
+
# command or block will be run. The special signal name “EXIT” or signal
|
18
|
+
# number zero will be invoked just prior to program termination.
|
19
|
+
#
|
20
|
+
# trap returns the previous handler for the given signal.
|
21
|
+
#
|
22
|
+
# @param sig [String, Symbol, Integer] signal name or number
|
23
|
+
# @param command [String, Proc] command to perform
|
8
24
|
def trap(sig, command = nil, &block)
|
9
25
|
return super(sig, command) if command.is_a? String
|
10
26
|
|
@@ -90,7 +90,7 @@ class ::OpenSSL::SSL::SSLSocket
|
|
90
90
|
|
91
91
|
# Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
|
92
92
|
# the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
|
93
|
-
# buffer to read into, otherwise a new string is allocated. If `
|
93
|
+
# buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
|
94
94
|
# given, reads into the given offset (in bytes) in the given buffer. If the
|
95
95
|
# given buffer offset is negative, it is calculated from the current end of
|
96
96
|
# the buffer (`-1` means the read data will be appended to the end of the
|
@@ -101,21 +101,21 @@ class ::OpenSSL::SSL::SSLSocket
|
|
101
101
|
#
|
102
102
|
# @param maxlen [Integer, nil] maximum bytes to read from socket
|
103
103
|
# @param buf [String, nil] buffer to read into
|
104
|
-
# @param
|
104
|
+
# @param buffer_pos [Number] buffer position to read into
|
105
105
|
# @return [String] buffer used for reading
|
106
|
-
def read(maxlen = nil, buf = nil, buffer_pos
|
107
|
-
return readpartial(maxlen, buf, buffer_pos
|
106
|
+
def read(maxlen = nil, buf = nil, buffer_pos = 0)
|
107
|
+
return readpartial(maxlen, buf, buffer_pos) if buf
|
108
108
|
|
109
109
|
buf = +''
|
110
110
|
return readpartial(maxlen, buf) if maxlen
|
111
111
|
|
112
|
-
readpartial(4096, buf,
|
112
|
+
readpartial(4096, buf, -1) while true
|
113
113
|
rescue EOFError
|
114
114
|
buf
|
115
115
|
end
|
116
116
|
|
117
117
|
# Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
|
118
|
-
# buffer to read into, otherwise a new string is allocated. If `
|
118
|
+
# buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
|
119
119
|
# given, reads into the given offset (in bytes) in the given buffer. If the
|
120
120
|
# given buffer offset is negative, it is calculated from the current end of
|
121
121
|
# the buffer (`-1` means the read data will be appended to the end of the
|
@@ -127,16 +127,16 @@ class ::OpenSSL::SSL::SSLSocket
|
|
127
127
|
#
|
128
128
|
# @param maxlen [Integer, nil] maximum bytes to read from socket
|
129
129
|
# @param buf [String, nil] buffer to read into
|
130
|
-
# @param
|
130
|
+
# @param buffer_pos [Number] buffer position to read into
|
131
131
|
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
132
132
|
# @return [String, nil] buffer used for reading or nil on `EOF`
|
133
|
-
def readpartial(maxlen, buf = +'', buffer_pos
|
134
|
-
if
|
133
|
+
def readpartial(maxlen, buf = +'', buffer_pos = 0, raise_on_eof = true)
|
134
|
+
if buffer_pos != 0
|
135
135
|
if (result = sysread(maxlen, +''))
|
136
|
-
if
|
136
|
+
if buffer_pos == -1
|
137
137
|
result = buf + result
|
138
138
|
else
|
139
|
-
result = buf[0...
|
139
|
+
result = buf[0...buffer_pos] + result
|
140
140
|
end
|
141
141
|
end
|
142
142
|
else
|
@@ -41,9 +41,9 @@ class Polyphony::Pipe
|
|
41
41
|
#
|
42
42
|
# @param len [Integer, nil] maximum bytes to read
|
43
43
|
# @param buf [String, nil] buffer to read into
|
44
|
-
# @param
|
44
|
+
# @param buffer_pos [Integer] buffer position to read into
|
45
45
|
# @return [String] read data
|
46
|
-
def read(len = nil, buf = nil, buffer_pos
|
46
|
+
def read(len = nil, buf = nil, buffer_pos = 0)
|
47
47
|
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
48
48
|
|
49
49
|
@read_buffer ||= +''
|
@@ -59,10 +59,10 @@ class Polyphony::Pipe
|
|
59
59
|
#
|
60
60
|
# @param len [Integer, nil] maximum bytes to read
|
61
61
|
# @param buf [String, nil] buffer to read into
|
62
|
-
# @param
|
62
|
+
# @param buffer_pos [Integer] buffer position to read into
|
63
63
|
# @param raise_on_eof [boolean] whether to raise an error if EOF is detected
|
64
64
|
# @return [String] read data
|
65
|
-
def readpartial(len, buf = +'', buffer_pos
|
65
|
+
def readpartial(len, buf = +'', buffer_pos = 0, raise_on_eof = true)
|
66
66
|
result = Polyphony.backend_read(self, buf, len, false, buffer_pos)
|
67
67
|
raise EOFError if !result && raise_on_eof
|
68
68
|
|
@@ -104,7 +104,7 @@ class Polyphony::Pipe
|
|
104
104
|
idx = @read_buffer.index(sep)
|
105
105
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
106
106
|
|
107
|
-
result = readpartial(8192, @read_buffer,
|
107
|
+
result = readpartial(8192, @read_buffer, -1)
|
108
108
|
return nil unless result
|
109
109
|
end
|
110
110
|
rescue EOFError
|