uringmachine 0.26.0 → 0.28.0
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/CHANGELOG.md +12 -0
- data/TODO.md +6 -16
- data/ext/um/um.c +80 -0
- data/ext/um/um.h +6 -1
- data/ext/um/um_class.c +219 -81
- data/ext/um/um_op.c +3 -1
- data/ext/um/um_stream.c +11 -0
- data/ext/um/um_stream_class.c +9 -0
- data/grant-2025/tasks.md +3 -16
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +5 -0
- data/test/test_async_op.rb +1 -1
- data/test/test_stream.rb +17 -0
- data/test/test_um.rb +315 -33
- metadata +1 -1
data/ext/um/um_op.c
CHANGED
|
@@ -18,9 +18,11 @@ const char * um_op_kind_name(enum um_op_kind kind) {
|
|
|
18
18
|
case OP_STATX: return "OP_STATX";
|
|
19
19
|
case OP_ACCEPT: return "OP_ACCEPT";
|
|
20
20
|
case OP_RECV: return "OP_RECV";
|
|
21
|
+
case OP_RECVMSG: return "OP_RECVMSG";
|
|
21
22
|
case OP_SEND: return "OP_SEND";
|
|
22
|
-
case OP_SENDV: return "OP_SENDV";
|
|
23
23
|
case OP_SEND_BUNDLE: return "OP_SEND_BUNDLE";
|
|
24
|
+
case OP_SENDMSG: return "OP_SENDMSG";
|
|
25
|
+
case OP_SENDV: return "OP_SENDV";
|
|
24
26
|
case OP_SOCKET: return "OP_SOCKET";
|
|
25
27
|
case OP_CONNECT: return "OP_CONNECT";
|
|
26
28
|
case OP_BIND: return "OP_BIND";
|
data/ext/um/um_stream.c
CHANGED
|
@@ -19,6 +19,7 @@ static inline void stream_check_truncate_buffer(struct um_stream *stream) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// returns true if eof
|
|
22
23
|
int stream_read_more(struct um_stream *stream) {
|
|
23
24
|
stream_check_truncate_buffer(stream);
|
|
24
25
|
|
|
@@ -104,6 +105,16 @@ VALUE stream_get_string(struct um_stream *stream, VALUE buf, ssize_t len) {
|
|
|
104
105
|
return buf;
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
VALUE stream_skip(struct um_stream *stream, size_t len) {
|
|
109
|
+
while (stream->len - stream->pos < len)
|
|
110
|
+
if (!stream_read_more(stream)) {
|
|
111
|
+
return Qnil;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
stream->pos += len;
|
|
115
|
+
return NUM2INT(len);
|
|
116
|
+
}
|
|
117
|
+
|
|
107
118
|
VALUE resp_get_line(struct um_stream *stream, VALUE out_buffer) {
|
|
108
119
|
char *start = RSTRING_PTR(stream->buffer) + stream->pos;
|
|
109
120
|
while (true) {
|
data/ext/um/um_stream_class.c
CHANGED
|
@@ -65,6 +65,14 @@ VALUE Stream_get_string(VALUE self, VALUE buf, VALUE len) {
|
|
|
65
65
|
return stream_get_string(stream, buf, NUM2LONG(len));
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// skips `len` bytes in the stream. This function returns nil if eof is
|
|
69
|
+
// encountered.
|
|
70
|
+
VALUE Stream_skip(VALUE self, VALUE len) {
|
|
71
|
+
struct um_stream *stream = Stream_data(self);
|
|
72
|
+
|
|
73
|
+
return stream_skip(stream, NUM2LONG(len));
|
|
74
|
+
}
|
|
75
|
+
|
|
68
76
|
VALUE Stream_resp_decode(VALUE self) {
|
|
69
77
|
struct um_stream *stream = Stream_data(self);
|
|
70
78
|
if (unlikely(stream->eof)) return Qnil;
|
|
@@ -104,6 +112,7 @@ void Init_Stream(void) {
|
|
|
104
112
|
|
|
105
113
|
rb_define_method(cStream, "get_line", Stream_get_line, 2);
|
|
106
114
|
rb_define_method(cStream, "get_string", Stream_get_string, 2);
|
|
115
|
+
rb_define_method(cStream, "skip", Stream_skip, 1);
|
|
107
116
|
|
|
108
117
|
rb_define_method(cStream, "resp_decode", Stream_resp_decode, 0);
|
|
109
118
|
|
data/grant-2025/tasks.md
CHANGED
|
@@ -129,10 +129,10 @@
|
|
|
129
129
|
|
|
130
130
|
- [v] Postgres test
|
|
131
131
|
|
|
132
|
-
- [
|
|
132
|
+
- [v] Ruby Fiber::Scheduler interface
|
|
133
133
|
- [v] Make a PR for resetting the scheduler and resetting the fiber non-blocking flag.
|
|
134
134
|
- [v] hook for close
|
|
135
|
-
- [
|
|
135
|
+
- [x] hooks for send/recv/sendmsg/recvmsg (Ruby core PR pending for send/recv)
|
|
136
136
|
|
|
137
137
|
- [v] SSL
|
|
138
138
|
- [v] setup custom BIO
|
|
@@ -147,22 +147,9 @@
|
|
|
147
147
|
- [ ] docs (similar to papercraft docs)
|
|
148
148
|
|
|
149
149
|
- [ ] Uma - web server
|
|
150
|
-
- [ ] child process workers
|
|
151
|
-
- [ ] reforking (following https://github.com/Shopify/pitchfork)
|
|
152
|
-
see also: https://byroot.github.io/ruby/performance/2025/03/04/the-pitchfork-story.html
|
|
153
|
-
- Monitor worker memory usage - how much is shared
|
|
154
|
-
- Choose worker with most served request count as "mold" for next generation
|
|
155
|
-
- Perform GC out of band, preferably when there are no active requests
|
|
156
|
-
https://railsatscale.com/2024-10-23-next-generation-oob-gc/
|
|
157
|
-
- When a worker is promoted to "mold", it:
|
|
158
|
-
- Stops `accept`ing requests
|
|
159
|
-
- When finally idle, calls `Process.warmup`
|
|
160
|
-
- Starts replacing sibling workers with forked workers
|
|
161
|
-
see also: https://www.youtube.com/watch?v=kAW5O2dkSU8
|
|
162
|
-
- [ ] Each worker is single-threaded (except for worker threads)
|
|
163
150
|
- [ ] Rack 3.0-compatible
|
|
164
151
|
see: https://github.com/socketry/protocol-rack
|
|
165
152
|
- [ ] Rails integration (Railtie)
|
|
166
153
|
see: https://github.com/socketry/falcon
|
|
167
154
|
- [ ] Benchmarks
|
|
168
|
-
- [ ] Add to the TechEmpower
|
|
155
|
+
- [ ] Add to the TechEmpower benchmarks
|
data/lib/uringmachine/version.rb
CHANGED
data/lib/uringmachine.rb
CHANGED
data/test/test_async_op.rb
CHANGED
data/test/test_stream.rb
CHANGED
|
@@ -98,6 +98,23 @@ class StreamTest < StreamBaseTest
|
|
|
98
98
|
ret = @stream.get_string(nil, -4)
|
|
99
99
|
assert_nil ret
|
|
100
100
|
end
|
|
101
|
+
|
|
102
|
+
def test_skip
|
|
103
|
+
machine.write(@wfd, "foobar")
|
|
104
|
+
machine.close(@wfd)
|
|
105
|
+
|
|
106
|
+
ret = @stream.get_string(nil, 2)
|
|
107
|
+
assert_equal 'fo', ret
|
|
108
|
+
|
|
109
|
+
ret = @stream.skip(2)
|
|
110
|
+
assert_equal 2, ret
|
|
111
|
+
|
|
112
|
+
ret = @stream.get_string(nil, 2)
|
|
113
|
+
assert_equal 'ar', ret
|
|
114
|
+
|
|
115
|
+
ret = @stream.skip(2)
|
|
116
|
+
assert_nil ret
|
|
117
|
+
end
|
|
101
118
|
end
|
|
102
119
|
|
|
103
120
|
class StreamRespTest < StreamBaseTest
|
data/test/test_um.rb
CHANGED
|
@@ -238,7 +238,38 @@ class ScheduleTest < UMBaseTest
|
|
|
238
238
|
assert_in_range 0..0.1, t1 - t0
|
|
239
239
|
end
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
def test_terminate
|
|
242
|
+
e = nil
|
|
243
|
+
f = machine.spin do
|
|
244
|
+
machine.sleep(1)
|
|
245
|
+
rescue UM::Terminate => e
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
machine.snooze
|
|
249
|
+
machine.terminate(f)
|
|
250
|
+
machine.snooze
|
|
251
|
+
assert_kind_of UM::Terminate, e
|
|
252
|
+
assert_equal true, f.done?
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def test_terminate_multi
|
|
256
|
+
f1 = machine.spin { machine.sleep(1) }
|
|
257
|
+
f2 = machine.spin { machine.sleep(1) }
|
|
258
|
+
f3 = machine.spin { machine.sleep(1) }
|
|
259
|
+
|
|
260
|
+
machine.snooze
|
|
261
|
+
machine.terminate(f1, f2)
|
|
262
|
+
machine.snooze
|
|
263
|
+
assert_equal true, f1.done?
|
|
264
|
+
assert_equal true, f2.done?
|
|
265
|
+
assert_nil f3.done?
|
|
266
|
+
|
|
267
|
+
machine.terminate(f3)
|
|
268
|
+
machine.snooze
|
|
269
|
+
assert_equal true, f3.done?
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
class TOError < StandardError; end
|
|
242
273
|
|
|
243
274
|
def test_timeout
|
|
244
275
|
buf = []
|
|
@@ -299,8 +330,8 @@ class ScheduleTest < UMBaseTest
|
|
|
299
330
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
300
331
|
end
|
|
301
332
|
|
|
302
|
-
class TO2Error <
|
|
303
|
-
class TO3Error <
|
|
333
|
+
class TO2Error < StandardError; end
|
|
334
|
+
class TO3Error < StandardError; end
|
|
304
335
|
|
|
305
336
|
def test_timeout_nested
|
|
306
337
|
e = nil
|
|
@@ -351,7 +382,7 @@ class SleepTest < UMBaseTest
|
|
|
351
382
|
assert_kind_of C, ret
|
|
352
383
|
end
|
|
353
384
|
|
|
354
|
-
class D <
|
|
385
|
+
class D < StandardError; end
|
|
355
386
|
|
|
356
387
|
def test_sleep_with_timeout
|
|
357
388
|
t0 = monotonic_clock
|
|
@@ -733,7 +764,7 @@ class ReadEachTest < UMBaseTest
|
|
|
733
764
|
class TOError < StandardError; end
|
|
734
765
|
|
|
735
766
|
def test_read_each_timeout
|
|
736
|
-
r,
|
|
767
|
+
r, _w = IO.pipe
|
|
737
768
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
|
738
769
|
|
|
739
770
|
bufs = []
|
|
@@ -955,7 +986,7 @@ class WritevTest < UMBaseTest
|
|
|
955
986
|
machine.join(f)
|
|
956
987
|
end
|
|
957
988
|
|
|
958
|
-
class TOError <
|
|
989
|
+
class TOError < StandardError; end
|
|
959
990
|
|
|
960
991
|
def test_writev_timeout
|
|
961
992
|
r, w = UM.pipe
|
|
@@ -1344,7 +1375,7 @@ class AcceptEachTest < UMBaseTest
|
|
|
1344
1375
|
def test_accept_each_closed
|
|
1345
1376
|
count = 0
|
|
1346
1377
|
done = nil
|
|
1347
|
-
|
|
1378
|
+
@machine.spin do
|
|
1348
1379
|
machine.accept_each(@server.fileno) do |fd|
|
|
1349
1380
|
count += 1
|
|
1350
1381
|
end
|
|
@@ -1639,8 +1670,6 @@ class SendvTest < UMBaseTest
|
|
|
1639
1670
|
end
|
|
1640
1671
|
|
|
1641
1672
|
def test_sendv
|
|
1642
|
-
skip "Unavailable on kernel version < 6.17" if UM.kernel_version < 617
|
|
1643
|
-
|
|
1644
1673
|
ret = machine.sendv(@s1, 'foo', 'bar', 'baz')
|
|
1645
1674
|
assert_equal 9, ret
|
|
1646
1675
|
|
|
@@ -1653,8 +1682,6 @@ class SendvTest < UMBaseTest
|
|
|
1653
1682
|
end
|
|
1654
1683
|
|
|
1655
1684
|
def test_sendv_io_buffer
|
|
1656
|
-
skip "Unavailable on kernel version < 6.17" if UM.kernel_version < 617
|
|
1657
|
-
|
|
1658
1685
|
buf1 = IO::Buffer.new(6)
|
|
1659
1686
|
buf1.set_string('foobar')
|
|
1660
1687
|
|
|
@@ -1673,8 +1700,6 @@ class SendvTest < UMBaseTest
|
|
|
1673
1700
|
end
|
|
1674
1701
|
|
|
1675
1702
|
def test_sendv_invalid_buffer
|
|
1676
|
-
skip "Unavailable on kernel version < 6.17" if UM.kernel_version < 617
|
|
1677
|
-
|
|
1678
1703
|
assert_raises(UM::Error) { machine.sendv(@s1, [], 'abc') }
|
|
1679
1704
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
1680
1705
|
assert_equal 0, machine.metrics[:ops_free]
|
|
@@ -1816,7 +1841,7 @@ class RecvEachTest < UMBaseTest
|
|
|
1816
1841
|
|
|
1817
1842
|
def test_recv_each_timeout
|
|
1818
1843
|
t = Thread.new do
|
|
1819
|
-
|
|
1844
|
+
@server.accept
|
|
1820
1845
|
sleep
|
|
1821
1846
|
end
|
|
1822
1847
|
|
|
@@ -1847,7 +1872,7 @@ class RecvEachTest < UMBaseTest
|
|
|
1847
1872
|
|
|
1848
1873
|
def test_recv_each_shutdown
|
|
1849
1874
|
t = Thread.new do
|
|
1850
|
-
|
|
1875
|
+
@server.accept
|
|
1851
1876
|
sleep
|
|
1852
1877
|
end
|
|
1853
1878
|
|
|
@@ -1861,7 +1886,7 @@ class RecvEachTest < UMBaseTest
|
|
|
1861
1886
|
bufs = []
|
|
1862
1887
|
e = nil
|
|
1863
1888
|
|
|
1864
|
-
|
|
1889
|
+
machine.spin {
|
|
1865
1890
|
machine.sleep(0.01)
|
|
1866
1891
|
machine.shutdown(fd, UM::SHUT_RDWR)
|
|
1867
1892
|
}
|
|
@@ -1881,6 +1906,244 @@ class RecvEachTest < UMBaseTest
|
|
|
1881
1906
|
end
|
|
1882
1907
|
end
|
|
1883
1908
|
|
|
1909
|
+
class SendRecvFdTest < UMBaseTest
|
|
1910
|
+
def setup
|
|
1911
|
+
@s1_fd, @s2_fd = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
1912
|
+
super
|
|
1913
|
+
end
|
|
1914
|
+
|
|
1915
|
+
def teardown
|
|
1916
|
+
[@s1_fd, @s2_fd].each { machine.close(it) rescue nil }
|
|
1917
|
+
super
|
|
1918
|
+
end
|
|
1919
|
+
|
|
1920
|
+
class TOError < StandardError; end
|
|
1921
|
+
|
|
1922
|
+
def test_send_recv_fd
|
|
1923
|
+
r_fd, w_fd = UM.pipe
|
|
1924
|
+
|
|
1925
|
+
res = machine.send_fd(@s1_fd, w_fd)
|
|
1926
|
+
assert_equal w_fd, res
|
|
1927
|
+
|
|
1928
|
+
fd = machine.recv_fd(@s2_fd)
|
|
1929
|
+
assert_kind_of Integer, fd
|
|
1930
|
+
refute_equal w_fd, fd
|
|
1931
|
+
|
|
1932
|
+
machine.close(w_fd)
|
|
1933
|
+
machine.write(fd, 'foobar')
|
|
1934
|
+
machine.close(fd)
|
|
1935
|
+
|
|
1936
|
+
buf = +''
|
|
1937
|
+
res = machine.read(r_fd, buf, 12)
|
|
1938
|
+
assert_equal 6, res
|
|
1939
|
+
assert_equal 'foobar', buf
|
|
1940
|
+
end
|
|
1941
|
+
|
|
1942
|
+
def test_send_recv_fd_multi
|
|
1943
|
+
r_fd, w_fd = UM.pipe
|
|
1944
|
+
|
|
1945
|
+
res = machine.send_fd(@s1_fd, w_fd)
|
|
1946
|
+
assert_equal w_fd, res
|
|
1947
|
+
|
|
1948
|
+
w_fd2 = machine.recv_fd(@s2_fd)
|
|
1949
|
+
assert_kind_of Integer, w_fd2
|
|
1950
|
+
refute_equal w_fd, w_fd2
|
|
1951
|
+
|
|
1952
|
+
res = machine.send_fd(@s1_fd, r_fd)
|
|
1953
|
+
assert_equal r_fd, res
|
|
1954
|
+
|
|
1955
|
+
r_fd2 = machine.recv_fd(@s2_fd)
|
|
1956
|
+
assert_kind_of Integer, r_fd2
|
|
1957
|
+
refute_equal r_fd, r_fd2
|
|
1958
|
+
|
|
1959
|
+
machine.close(w_fd)
|
|
1960
|
+
machine.write(w_fd2, 'foobar')
|
|
1961
|
+
machine.close(w_fd2)
|
|
1962
|
+
|
|
1963
|
+
buf = +''
|
|
1964
|
+
res = machine.read(r_fd, buf, 12)
|
|
1965
|
+
assert_equal 6, res
|
|
1966
|
+
assert_equal 'foobar', buf
|
|
1967
|
+
ensure
|
|
1968
|
+
machine.close(r_fd) if r_fd rescue nil
|
|
1969
|
+
machine.close(w_fd) if w_fd rescue nil
|
|
1970
|
+
machine.close(r_fd2) if r_fd2 rescue nil
|
|
1971
|
+
machine.close(w_fd2) if w_fd2 rescue nil
|
|
1972
|
+
|
|
1973
|
+
end
|
|
1974
|
+
|
|
1975
|
+
def test_send_recv_fd_mixed_multi
|
|
1976
|
+
r_fd, w_fd = UM.pipe
|
|
1977
|
+
|
|
1978
|
+
machine.send(@s1_fd, 'hi', 2, 0)
|
|
1979
|
+
buf = +''
|
|
1980
|
+
ret = machine.recv(@s2_fd, buf, 2, 0)
|
|
1981
|
+
assert_equal 2, ret
|
|
1982
|
+
assert_equal 'hi', buf
|
|
1983
|
+
|
|
1984
|
+
res = machine.send_fd(@s1_fd, w_fd)
|
|
1985
|
+
assert_equal w_fd, res
|
|
1986
|
+
|
|
1987
|
+
w_fd2 = machine.recv_fd(@s2_fd)
|
|
1988
|
+
assert_kind_of Integer, w_fd2
|
|
1989
|
+
refute_equal w_fd, w_fd2
|
|
1990
|
+
|
|
1991
|
+
res = machine.send_fd(@s1_fd, r_fd)
|
|
1992
|
+
assert_equal r_fd, res
|
|
1993
|
+
|
|
1994
|
+
r_fd2 = machine.recv_fd(@s2_fd)
|
|
1995
|
+
assert_kind_of Integer, r_fd2
|
|
1996
|
+
refute_equal r_fd, r_fd2
|
|
1997
|
+
|
|
1998
|
+
machine.close(w_fd)
|
|
1999
|
+
machine.write(w_fd2, 'foobar')
|
|
2000
|
+
machine.close(w_fd2)
|
|
2001
|
+
|
|
2002
|
+
buf = +''
|
|
2003
|
+
res = machine.read(r_fd, buf, 12)
|
|
2004
|
+
assert_equal 6, res
|
|
2005
|
+
assert_equal 'foobar', buf
|
|
2006
|
+
ensure
|
|
2007
|
+
machine.close(r_fd) if r_fd rescue nil
|
|
2008
|
+
machine.close(w_fd) if w_fd rescue nil
|
|
2009
|
+
machine.close(r_fd2) if r_fd2 rescue nil
|
|
2010
|
+
machine.close(w_fd2) if w_fd2 rescue nil
|
|
2011
|
+
|
|
2012
|
+
end
|
|
2013
|
+
|
|
2014
|
+
def test_send_recv_fd_inverse
|
|
2015
|
+
r_fd, w_fd = UM.pipe
|
|
2016
|
+
|
|
2017
|
+
res = machine.send_fd(@s2_fd, w_fd)
|
|
2018
|
+
assert_equal w_fd, res
|
|
2019
|
+
|
|
2020
|
+
fd = machine.recv_fd(@s1_fd)
|
|
2021
|
+
assert_kind_of Integer, fd
|
|
2022
|
+
refute_equal w_fd, fd
|
|
2023
|
+
|
|
2024
|
+
machine.close(w_fd)
|
|
2025
|
+
machine.write(fd, 'foobar')
|
|
2026
|
+
machine.close(fd)
|
|
2027
|
+
|
|
2028
|
+
buf = +''
|
|
2029
|
+
res = machine.read(r_fd, buf, 12)
|
|
2030
|
+
assert_equal 6, res
|
|
2031
|
+
assert_equal 'foobar', buf
|
|
2032
|
+
end
|
|
2033
|
+
|
|
2034
|
+
def test_send_recv_fd_fork
|
|
2035
|
+
pid = fork do
|
|
2036
|
+
m = UM.new
|
|
2037
|
+
fd = m.recv_fd(@s2_fd)
|
|
2038
|
+
m.write(fd, 'Hello!')
|
|
2039
|
+
ensure
|
|
2040
|
+
m.close(fd) rescue nil
|
|
2041
|
+
end
|
|
2042
|
+
|
|
2043
|
+
r_fd, w_fd = UM.pipe
|
|
2044
|
+
|
|
2045
|
+
res = machine.send_fd(@s1_fd, w_fd)
|
|
2046
|
+
assert_equal w_fd, res
|
|
2047
|
+
Process.wait(pid)
|
|
2048
|
+
pid = nil
|
|
2049
|
+
machine.close(w_fd)
|
|
2050
|
+
|
|
2051
|
+
buf = +''
|
|
2052
|
+
len = machine.timeout(1, TOError) { machine.read(r_fd, buf, 12) }
|
|
2053
|
+
assert_equal 6, len
|
|
2054
|
+
assert_equal 'Hello!', buf
|
|
2055
|
+
ensure
|
|
2056
|
+
if pid
|
|
2057
|
+
Process.kill('KILL', pid) rescue nil
|
|
2058
|
+
Process.wait(pid) rescue nil
|
|
2059
|
+
end
|
|
2060
|
+
machine.close(r_fd) rescue nil
|
|
2061
|
+
machine.close(w_fd) rescue nil
|
|
2062
|
+
end
|
|
2063
|
+
|
|
2064
|
+
def test_send_recv_fd_fork_mixed_msgs
|
|
2065
|
+
skip
|
|
2066
|
+
|
|
2067
|
+
pid = fork do
|
|
2068
|
+
m = UM.new
|
|
2069
|
+
buf = +''
|
|
2070
|
+
ret = m.recv(@s2_fd, buf, 128, 0)
|
|
2071
|
+
p forked_recv: buf, ret: ret
|
|
2072
|
+
ret = m.send(@s2_fd, buf, buf.bytesize, 0)
|
|
2073
|
+
p forked_send: buf, ret: ret
|
|
2074
|
+
fd = m.recv_fd(@s2_fd)
|
|
2075
|
+
p forked_recv_fd: fd
|
|
2076
|
+
ret = m.send(@s2_fd, buf, buf.bytesize, 0)
|
|
2077
|
+
p forked_send: buf, ret: ret
|
|
2078
|
+
|
|
2079
|
+
m.write(fd, 'foo')
|
|
2080
|
+
ensure
|
|
2081
|
+
m.close(fd) if fd rescue nil
|
|
2082
|
+
end
|
|
2083
|
+
|
|
2084
|
+
buf = +''
|
|
2085
|
+
|
|
2086
|
+
machine.send(@s1_fd, 'coocoo', 6, 0)
|
|
2087
|
+
machine.recv(@s1_fd, buf, 128, 0)
|
|
2088
|
+
assert_equal 'coocoo', buf
|
|
2089
|
+
|
|
2090
|
+
r_fd, w_fd = UM.pipe
|
|
2091
|
+
machine.send_fd(@s1_fd, w_fd)
|
|
2092
|
+
machine.recv(@s1_fd, buf, 128, 0)
|
|
2093
|
+
assert_equal 'coocoo', buf
|
|
2094
|
+
|
|
2095
|
+
machine.read(r_fd, buf, 128)
|
|
2096
|
+
assert_equal 'foo', buf
|
|
2097
|
+
ensure
|
|
2098
|
+
if pid
|
|
2099
|
+
Process.kill('KILL', pid) rescue nil
|
|
2100
|
+
Process.wait(pid) rescue nil
|
|
2101
|
+
end
|
|
2102
|
+
machine.close(r_fd) rescue nil
|
|
2103
|
+
machine.close(w_fd) rescue nil
|
|
2104
|
+
end
|
|
2105
|
+
|
|
2106
|
+
def test_send_recv_fd_fork_inverse
|
|
2107
|
+
pid = fork do
|
|
2108
|
+
m = UM.new
|
|
2109
|
+
r, w = UM.pipe
|
|
2110
|
+
m.send_fd(@s2_fd, r)
|
|
2111
|
+
|
|
2112
|
+
buf = +''
|
|
2113
|
+
m.read(r, buf, 128)
|
|
2114
|
+
m.send(@s2_fd, buf)
|
|
2115
|
+
end
|
|
2116
|
+
|
|
2117
|
+
assert_raises(Errno::EINVAL) { machine.recv_fd(@s1_fd) }
|
|
2118
|
+
ensure
|
|
2119
|
+
if pid
|
|
2120
|
+
Process.kill('KILL', pid) rescue nil
|
|
2121
|
+
Process.wait(pid) rescue nil
|
|
2122
|
+
end
|
|
2123
|
+
machine.close(w) rescue nil
|
|
2124
|
+
end
|
|
2125
|
+
|
|
2126
|
+
def test_send_fd_bad_sock_fd
|
|
2127
|
+
_r_fd, w_fd = UM.pipe
|
|
2128
|
+
assert_raises(Errno::ENOTSOCK) { machine.send_fd(0, w_fd) }
|
|
2129
|
+
end
|
|
2130
|
+
|
|
2131
|
+
def test_send_fd_bad_fd
|
|
2132
|
+
assert_raises(TypeError) { machine.send_fd(@s1_fd, nil) }
|
|
2133
|
+
assert_raises(Errno::EBADF) { machine.send_fd(@s1_fd, 1111) }
|
|
2134
|
+
end
|
|
2135
|
+
|
|
2136
|
+
def test_recv_fd_bad_msg
|
|
2137
|
+
buf = "\0" * 1000
|
|
2138
|
+
machine.write(@s1_fd, buf)
|
|
2139
|
+
|
|
2140
|
+
assert_raises(Errno::EINVAL) {
|
|
2141
|
+
res = machine.recv_fd(@s2_fd)
|
|
2142
|
+
p res: res
|
|
2143
|
+
}
|
|
2144
|
+
end
|
|
2145
|
+
end
|
|
2146
|
+
|
|
1884
2147
|
class BindTest < UMBaseTest
|
|
1885
2148
|
def setup
|
|
1886
2149
|
super
|
|
@@ -2836,23 +3099,6 @@ class SendBundleTest < UMBaseTest
|
|
|
2836
3099
|
end
|
|
2837
3100
|
end
|
|
2838
3101
|
|
|
2839
|
-
class NonBlockTest < UMBaseTest
|
|
2840
|
-
def test_io_nonblock?
|
|
2841
|
-
assert_equal false, UM.io_nonblock?(STDIN)
|
|
2842
|
-
end
|
|
2843
|
-
|
|
2844
|
-
def test_io_set_nonblock
|
|
2845
|
-
r, _w = IO.pipe
|
|
2846
|
-
assert_equal true, UM.io_nonblock?(r)
|
|
2847
|
-
|
|
2848
|
-
UM.io_set_nonblock(r, false)
|
|
2849
|
-
assert_equal false, UM.io_nonblock?(r)
|
|
2850
|
-
|
|
2851
|
-
UM.io_set_nonblock(r, true)
|
|
2852
|
-
assert_equal true, UM.io_nonblock?(r)
|
|
2853
|
-
end
|
|
2854
|
-
end
|
|
2855
|
-
|
|
2856
3102
|
class MetricsTest < UMBaseTest
|
|
2857
3103
|
def test_metrics_empty
|
|
2858
3104
|
assert_equal({
|
|
@@ -3159,3 +3405,39 @@ class FileWatchTest < UMBaseTest
|
|
|
3159
3405
|
machine.join(f)
|
|
3160
3406
|
end
|
|
3161
3407
|
end
|
|
3408
|
+
|
|
3409
|
+
class SetChildSubreaperTest < Minitest::Test
|
|
3410
|
+
def test_pr_set_child_subreaper
|
|
3411
|
+
r, w = IO.pipe
|
|
3412
|
+
UM.pr_set_child_subreaper(true)
|
|
3413
|
+
|
|
3414
|
+
child_pid = fork {
|
|
3415
|
+
r2, w2 = IO.pipe
|
|
3416
|
+
pid = fork {
|
|
3417
|
+
r.close
|
|
3418
|
+
w.close
|
|
3419
|
+
w2.close
|
|
3420
|
+
r2.read
|
|
3421
|
+
r2.close
|
|
3422
|
+
sleep(0.01)
|
|
3423
|
+
}
|
|
3424
|
+
w << pid
|
|
3425
|
+
w.close
|
|
3426
|
+
r2.close
|
|
3427
|
+
w2 << 'done'
|
|
3428
|
+
w2.close
|
|
3429
|
+
}
|
|
3430
|
+
Process.wait(child_pid)
|
|
3431
|
+
|
|
3432
|
+
w.close
|
|
3433
|
+
msg = r.read
|
|
3434
|
+
r.close
|
|
3435
|
+
|
|
3436
|
+
refute msg.empty?
|
|
3437
|
+
grand_child_pid = msg.to_i
|
|
3438
|
+
refute_equal 0, grand_child_pid
|
|
3439
|
+
|
|
3440
|
+
res = Process.wait(grand_child_pid)
|
|
3441
|
+
assert_equal grand_child_pid, res
|
|
3442
|
+
end
|
|
3443
|
+
end
|