uringmachine 0.6 → 0.7
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 +8 -0
- data/TODO.md +0 -1
- data/ext/um/um.c +37 -1
- data/ext/um/um.h +2 -0
- data/ext/um/um_class.c +7 -0
- data/lib/uringmachine/version.rb +1 -1
- data/test/run.rb +5 -0
- data/test/test_um.rb +58 -14
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7c0b7cfea4bdb08c954cf8dcef6cc776e4eb73e64fc366a43042f7a62902430
|
4
|
+
data.tar.gz: 83f60da253aa4ab69ef98a96205995b258c0d4a6925385818e34d2cb9fd26a0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54d58ae7aedc3f7444cff6d8b4afbf4845ba0ddf6ae5a662b60b04b83c81b7e2af35c1e46a1f3827adb07bf95c4677b4253774bd50c590541177a5a251d7f2b4
|
7
|
+
data.tar.gz: 9a6d69766b3d17c5b1593bd153608f846370c32bd7219796f4fbe677c379724aa1186f70a5cf4cbb797817e4564bdff01ab5a5a3514e803ac8ead5b949899fde
|
data/CHANGELOG.md
CHANGED
data/TODO.md
CHANGED
data/ext/um/um.c
CHANGED
@@ -175,8 +175,28 @@ inline VALUE process_runqueue_op(struct um *machine, struct um_op *op) {
|
|
175
175
|
inline VALUE um_fiber_switch(struct um *machine) {
|
176
176
|
while (true) {
|
177
177
|
struct um_op *op = um_runqueue_shift(machine);
|
178
|
-
if (op)
|
178
|
+
if (op) {
|
179
|
+
// in case of a snooze, we need to prevent a situation where completions
|
180
|
+
// are not processed because the runqueue is never empty. Theoretically,
|
181
|
+
// we can still have a situation where multiple fibers are all doing a
|
182
|
+
// snooze repeatedly, which can prevent completions from being processed.
|
183
|
+
|
184
|
+
// is the op a snooze op and is this the same fiber as the current one?
|
185
|
+
if (unlikely(op->kind == OP_SCHEDULE && op->fiber == rb_fiber_current())) {
|
186
|
+
// are there any pending ops (i.e. waiting for completion)?
|
187
|
+
if (machine->pending_count > 0) {
|
188
|
+
// if yes, process completions, get runqueue head, put original op
|
189
|
+
// back on runqueue.
|
190
|
+
um_wait_for_and_process_ready_cqes(machine);
|
191
|
+
struct um_op *op2 = um_runqueue_shift(machine);
|
192
|
+
if (likely(op2 && op2 != op)) {
|
193
|
+
um_runqueue_push(machine, op);
|
194
|
+
op = op2;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
179
198
|
return process_runqueue_op(machine, op);
|
199
|
+
}
|
180
200
|
|
181
201
|
um_wait_for_and_process_ready_cqes(machine);
|
182
202
|
}
|
@@ -529,6 +549,22 @@ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
|
|
529
549
|
return raise_if_exception(ret);
|
530
550
|
}
|
531
551
|
|
552
|
+
VALUE um_shutdown(struct um *machine, int fd, int how) {
|
553
|
+
VALUE ret = Qnil;
|
554
|
+
|
555
|
+
struct um_op op;
|
556
|
+
um_prep_op(machine, &op, OP_SHUTDOWN);
|
557
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
558
|
+
io_uring_prep_shutdown(sqe, fd, how);
|
559
|
+
|
560
|
+
ret = um_fiber_switch(machine);
|
561
|
+
if (um_check_completion(machine, &op))
|
562
|
+
ret = INT2NUM(op.result.res);
|
563
|
+
|
564
|
+
RB_GC_GUARD(ret);
|
565
|
+
return raise_if_exception(ret);
|
566
|
+
}
|
567
|
+
|
532
568
|
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
|
533
569
|
struct um_op op;
|
534
570
|
um_prep_op(machine, &op, OP_BIND);
|
data/ext/um/um.h
CHANGED
@@ -37,6 +37,7 @@ enum op_kind {
|
|
37
37
|
OP_LISTEN,
|
38
38
|
OP_GETSOCKOPT,
|
39
39
|
OP_SETSOCKOPT,
|
40
|
+
OP_SHUTDOWN,
|
40
41
|
|
41
42
|
OP_FUTEX_WAIT,
|
42
43
|
OP_FUTEX_WAKE,
|
@@ -220,6 +221,7 @@ VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrl
|
|
220
221
|
VALUE um_listen(struct um *machine, int fd, int backlog);
|
221
222
|
VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
|
222
223
|
VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value);
|
224
|
+
VALUE um_shutdown(struct um *machine, int fd, int how);
|
223
225
|
|
224
226
|
void um_async_op_set(VALUE self, struct um *machine, struct um_op *op);
|
225
227
|
VALUE um_async_op_await(struct um_async_op *async_op);
|
data/ext/um/um_class.c
CHANGED
@@ -150,6 +150,12 @@ VALUE UM_socket(VALUE self, VALUE domain, VALUE type, VALUE protocol, VALUE flag
|
|
150
150
|
return um_socket(machine, NUM2INT(domain), NUM2INT(type), NUM2INT(protocol), NUM2UINT(flags));
|
151
151
|
}
|
152
152
|
|
153
|
+
VALUE UM_shutdown(VALUE self, VALUE fd, VALUE how) {
|
154
|
+
struct um *machine = um_get_machine(self);
|
155
|
+
return um_shutdown(machine, NUM2INT(fd), NUM2INT(how));
|
156
|
+
|
157
|
+
}
|
158
|
+
|
153
159
|
VALUE UM_connect(VALUE self, VALUE fd, VALUE host, VALUE port) {
|
154
160
|
struct um *machine = um_get_machine(self);
|
155
161
|
|
@@ -350,6 +356,7 @@ void Init_UM(void) {
|
|
350
356
|
rb_define_method(cUM, "send", UM_send, 4);
|
351
357
|
rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
|
352
358
|
rb_define_method(cUM, "socket", UM_socket, 4);
|
359
|
+
rb_define_method(cUM, "shutdown", UM_shutdown, 2);
|
353
360
|
|
354
361
|
rb_define_method(cUM, "prep_timeout", UM_prep_timeout, 1);
|
355
362
|
|
data/lib/uringmachine/version.rb
CHANGED
data/test/run.rb
ADDED
data/test/test_um.rb
CHANGED
@@ -514,7 +514,7 @@ class WriteTest < UMBaseTest
|
|
514
514
|
end
|
515
515
|
end
|
516
516
|
|
517
|
-
class
|
517
|
+
class CloseTest < UMBaseTest
|
518
518
|
def test_close
|
519
519
|
r, w = IO.pipe
|
520
520
|
machine.write(w.fileno, 'foo')
|
@@ -529,6 +529,54 @@ class Closetest < UMBaseTest
|
|
529
529
|
end
|
530
530
|
end
|
531
531
|
|
532
|
+
class ShutdownTest < UMBaseTest
|
533
|
+
def make_socket_pair
|
534
|
+
port = 10000 + rand(30000)
|
535
|
+
server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
536
|
+
@machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
|
537
|
+
@machine.bind(server_fd, '127.0.0.1', port)
|
538
|
+
@machine.listen(server_fd, UM::SOMAXCONN)
|
539
|
+
|
540
|
+
client_conn_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
541
|
+
@machine.connect(client_conn_fd, '127.0.0.1', port)
|
542
|
+
|
543
|
+
server_conn_fd = @machine.accept(server_fd)
|
544
|
+
|
545
|
+
@machine.close(server_fd)
|
546
|
+
[client_conn_fd, server_conn_fd]
|
547
|
+
end
|
548
|
+
|
549
|
+
def test_shutdown
|
550
|
+
c_fd, s_fd = make_socket_pair
|
551
|
+
res = @machine.send(c_fd, 'abc', 3, 0)
|
552
|
+
assert_equal 3, res
|
553
|
+
|
554
|
+
buf = +''
|
555
|
+
res = @machine.recv(s_fd, buf, 256, 0)
|
556
|
+
assert_equal 3, res
|
557
|
+
assert_equal 'abc', buf
|
558
|
+
|
559
|
+
res = @machine.shutdown(c_fd, UM::SHUT_WR)
|
560
|
+
assert_equal 0, res
|
561
|
+
|
562
|
+
assert_raises(Errno::EPIPE) { @machine.send(c_fd, 'abc', 3, 0) }
|
563
|
+
|
564
|
+
res = @machine.shutdown(s_fd, UM::SHUT_RD)
|
565
|
+
assert_equal 0, res
|
566
|
+
|
567
|
+
res = @machine.recv(s_fd, buf, 256, 0)
|
568
|
+
assert_equal 0, res
|
569
|
+
|
570
|
+
res = @machine.shutdown(c_fd, UM::SHUT_RDWR)
|
571
|
+
assert_equal 0, res
|
572
|
+
|
573
|
+
assert_raises(Errno::EINVAL) { @machine.shutdown(c_fd, -9999) }
|
574
|
+
ensure
|
575
|
+
@machine.close(c_fd)
|
576
|
+
@machine.close(s_fd)
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
532
580
|
class AcceptTest < UMBaseTest
|
533
581
|
def setup
|
534
582
|
super
|
@@ -917,32 +965,28 @@ class QueueTest < UMBaseTest
|
|
917
965
|
q = UM::Queue.new
|
918
966
|
buf = []
|
919
967
|
|
920
|
-
|
968
|
+
machine.spin do
|
921
969
|
buf << [1, machine.pop(q)]
|
922
|
-
machine.yield
|
923
970
|
end
|
924
971
|
|
925
|
-
machine.
|
926
|
-
|
927
|
-
f2 = Fiber.new do
|
972
|
+
machine.spin do
|
928
973
|
buf << [2, machine.pop(q)]
|
929
|
-
machine.yield
|
930
974
|
end
|
931
975
|
|
932
|
-
machine.schedule(f2, nil)
|
933
|
-
|
934
976
|
machine.snooze
|
935
977
|
assert_equal [], buf
|
978
|
+
assert_equal 2, machine.pending_count
|
936
979
|
|
937
980
|
machine.push(q, :foo)
|
938
981
|
assert_equal 1, q.count
|
939
|
-
machine.
|
982
|
+
machine.snooze
|
983
|
+
assert_equal 1, machine.pending_count
|
940
984
|
assert_equal [[1, :foo]], buf
|
941
985
|
|
942
986
|
machine.push(q, :bar)
|
943
987
|
assert_equal 1, q.count
|
944
988
|
|
945
|
-
machine.
|
989
|
+
machine.snooze
|
946
990
|
assert_equal [[1, :foo], [2, :bar]], buf
|
947
991
|
assert_equal 0, q.count
|
948
992
|
end
|
@@ -969,7 +1013,7 @@ class QueueTest < UMBaseTest
|
|
969
1013
|
end
|
970
1014
|
machine.schedule(f2, nil)
|
971
1015
|
|
972
|
-
|
1016
|
+
machine.snooze
|
973
1017
|
|
974
1018
|
assert_equal [[1, :bar], [2, :foo]], buf.sort
|
975
1019
|
assert_equal 0, q.count
|
@@ -996,12 +1040,12 @@ class QueueTest < UMBaseTest
|
|
996
1040
|
end
|
997
1041
|
machine.schedule(f2, nil)
|
998
1042
|
|
999
|
-
machine.
|
1043
|
+
machine.snooze
|
1000
1044
|
|
1001
1045
|
assert_equal [[1, :foo]], buf
|
1002
1046
|
machine.push(q, :bar)
|
1003
1047
|
|
1004
|
-
machine.
|
1048
|
+
machine.snooze
|
1005
1049
|
assert_equal [[1, :foo], [2, :bar]], buf
|
1006
1050
|
end
|
1007
1051
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uringmachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.7'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-28 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rake-compiler
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- lib/uringmachine/version.rb
|
137
137
|
- supressions/ruby.supp
|
138
138
|
- test/helper.rb
|
139
|
+
- test/run.rb
|
139
140
|
- test/test_actor.rb
|
140
141
|
- test/test_async_op.rb
|
141
142
|
- test/test_ssl.rb
|