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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba017ea6da0eb880e2366157a7f1ff6ea936d32816ed2be45e3b3ca96b3c7408
4
- data.tar.gz: 22f556023080078623fd8618122fe6707fa4cfdf6654b6c43e122f524c91c645
3
+ metadata.gz: c42e434298bf496752efc6fe6a4cc81d04857f28f1151cfc3165ac3c288ec6a2
4
+ data.tar.gz: ec176b165f129aa7d1b6d0bdbc5f4b7e55d5e553569061d89956d0b1aee68503
5
5
  SHA512:
6
- metadata.gz: c08b772dd22791c297fc38dab3e8a73453ace1b54ee5c9e7b31ef127598987efd37fdfebf009b9202d3b550674006caf380a0e20fb50e4c2a3bee7e302afa97b
7
- data.tar.gz: 1f35f727b26808a0bca4c24c19ee41ef4400766ec1b3b7033dbd39fea635168f93757825c4bf9e38d065c66652cd5120ce1880f8ef484233abdaa8bd9dff3b84
6
+ metadata.gz: 1760b892d6ae21c7007fd0a109a78d631da4ae9a79667ad85bc4740ac0e339802ca9cb0bc34114570bf7e6113e4dab704a1c9f40513a196e840b759a494a35b9
7
+ data.tar.gz: 7dfe1426f96ecd1e99af4224c34d3b3173858b5d6c156b949314a0e80c34b836ae738e930ed26662319bc6700401cd0b369028e172ed1b70982cee64fb13f7a1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 0.28.0 2026-02-19
2
+
3
+ - Add `#terminate`
4
+ - Make `#sendv` available also for older kernels (using `#writev`)
5
+ - Implement `Stream#skip`
6
+ - Inherit exceptions from `StandardError` instead of `RuntimeError`
7
+
8
+ # 0.27.0 2026-02-15
9
+
10
+ - Add `.pr_set_child_subreaper` method
11
+ - Add `#send_fd`, `#recv_fd` methods
12
+
1
13
  # 0.26.0 2026-02-13
2
14
 
3
15
  - Reimplement um_op lifecycle tracking
data/TODO.md CHANGED
@@ -1,9 +1,11 @@
1
1
  ## immediate
2
2
 
3
- - Fix all futex value (Queue, Mutex) to be properly aligned
3
+ - Add tests for support for Set in `machine#await_fibers`
4
+ - Add tests for support for Set, Array in `machine#join`
4
5
 
5
- ## Buffer rings - automatic management
6
+ - (?) Fix all futex value (Queue, Mutex) to be properly aligned
6
7
 
8
+ ## Buffer rings - automatic management
7
9
  - Take the buffer_pool branch, rewrite it
8
10
  - Allow multiple stream modes:
9
11
  - :buffer_pool - uses buffer rings
@@ -64,19 +66,6 @@ stream = UM::Stream.new(conn) # io mode
64
66
  - select on multiple queues (ala Go)
65
67
  - select on mixture of queues and fds
66
68
 
67
- (see also simplified op management below)
68
-
69
- ## simplified op management
70
-
71
- Op lifecycle management can be much much simpler
72
-
73
- - make all ops heap-allocated
74
- - clear up state transitions:
75
-
76
- - kernel-side state: unsubmitted, submitted, completed, done (for multishot ops)
77
- - app-side state: unsubmitted, submitted, ...
78
-
79
-
80
69
  ## ops
81
70
 
82
71
  - splice / - tee
@@ -104,7 +93,8 @@ We're still missing:
104
93
  - ability to supply buffer to `get_line` and `get_string`
105
94
  - allow read to eof, maybe with `read_to_eof`
106
95
 
107
- For the sake of performance, simplicity and explicitness, we change the API as follows:
96
+ For the sake of performance, simplicity and explicitness, we change the API as
97
+ follows:
108
98
 
109
99
  ```ruby
110
100
  stream.get_line(buf, limit)
data/ext/um/um.c CHANGED
@@ -977,6 +977,86 @@ VALUE um_shutdown_async(struct um *machine, int fd, int how) {
977
977
  return INT2NUM(fd);
978
978
  }
979
979
 
980
+ struct send_recv_fd_ctx {
981
+ struct msghdr msgh;
982
+ char iobuf[1];
983
+ struct iovec iov;
984
+ union { // Ancillary data buffer, wrapped in a union for alignment
985
+ char buf[CMSG_SPACE(sizeof(int))];
986
+ struct cmsghdr align;
987
+ } u;
988
+ };
989
+
990
+ inline void send_recv_fd_setup_ctx(struct send_recv_fd_ctx *ctx, int fd) {
991
+ ctx->iov.iov_base = ctx->iobuf;
992
+ ctx->iov.iov_len = sizeof(ctx->iobuf);
993
+
994
+ memset(&ctx->msgh, 0, sizeof(ctx->msgh));
995
+ ctx->msgh.msg_iov = &ctx->iov;
996
+ ctx->msgh.msg_iovlen = 1;
997
+ ctx->msgh.msg_control = ctx->u.buf;
998
+ ctx->msgh.msg_controllen = sizeof(ctx->u.buf);
999
+
1000
+ if (fd > 0) {
1001
+ struct cmsghdr *cmsgp = CMSG_FIRSTHDR(&ctx->msgh);
1002
+ cmsgp->cmsg_level = SOL_SOCKET;
1003
+ cmsgp->cmsg_type = SCM_RIGHTS;
1004
+ cmsgp->cmsg_len = CMSG_LEN(sizeof(fd));
1005
+ memcpy(CMSG_DATA(cmsgp), &fd, sizeof(fd));
1006
+ }
1007
+ }
1008
+
1009
+ VALUE um_send_fd(struct um *machine, int sock_fd, int fd) {
1010
+ struct send_recv_fd_ctx ctx;
1011
+ send_recv_fd_setup_ctx(&ctx, fd);
1012
+
1013
+ VALUE ret = Qnil;
1014
+ struct um_op *op = um_op_acquire(machine);
1015
+ um_prep_op(machine, op, OP_SENDMSG, 2, 0);
1016
+ struct io_uring_sqe *sqe = um_get_sqe(machine, op);
1017
+ io_uring_prep_sendmsg(sqe, sock_fd, &ctx.msgh, 0);
1018
+
1019
+ ret = um_yield(machine);
1020
+
1021
+ if (likely(um_verify_op_completion(machine, op, true))) ret = INT2NUM(fd);
1022
+ um_op_release(machine, op);
1023
+
1024
+ RAISE_IF_EXCEPTION(ret);
1025
+ RB_GC_GUARD(ret);
1026
+ return ret;
1027
+ }
1028
+
1029
+ inline int recv_fd_get_fd(struct send_recv_fd_ctx *ctx) {
1030
+ int fd;
1031
+ struct cmsghdr *cmsgp = CMSG_FIRSTHDR(&ctx->msgh);
1032
+
1033
+ if (cmsgp == NULL || cmsgp->cmsg_len != CMSG_LEN(sizeof(int)) ||
1034
+ cmsgp->cmsg_level != SOL_SOCKET || cmsgp->cmsg_type != SCM_RIGHTS
1035
+ ) um_raise_on_error_result(-EINVAL);
1036
+
1037
+ memcpy(&fd, CMSG_DATA(cmsgp), sizeof(int));
1038
+ return fd;
1039
+ }
1040
+
1041
+ VALUE um_recv_fd(struct um *machine, int sock_fd) {
1042
+ struct send_recv_fd_ctx ctx;
1043
+ send_recv_fd_setup_ctx(&ctx, -1);
1044
+
1045
+ struct um_op *op = um_op_acquire(machine);
1046
+ um_prep_op(machine, op, OP_RECVMSG, 2, 0);
1047
+ struct io_uring_sqe *sqe = um_get_sqe(machine, op);
1048
+ io_uring_prep_recvmsg(sqe, sock_fd, &ctx.msgh, 0);
1049
+
1050
+ VALUE ret = um_yield(machine);
1051
+
1052
+ if (likely(um_verify_op_completion(machine, op, true))) ret = INT2NUM(recv_fd_get_fd(&ctx));
1053
+ um_op_release(machine, op);
1054
+
1055
+ RAISE_IF_EXCEPTION(ret);
1056
+ RB_GC_GUARD(ret);
1057
+ return ret;
1058
+ }
1059
+
980
1060
  VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
981
1061
  struct um_op *op = um_op_acquire(machine);
982
1062
  um_prep_op(machine, op, OP_OPEN, 2, 0);
data/ext/um/um.h CHANGED
@@ -51,9 +51,11 @@ enum um_op_kind {
51
51
 
52
52
  OP_ACCEPT,
53
53
  OP_RECV,
54
+ OP_RECVMSG,
54
55
  OP_SEND,
55
- OP_SENDV,
56
56
  OP_SEND_BUNDLE,
57
+ OP_SENDMSG,
58
+ OP_SENDV,
57
59
  OP_SOCKET,
58
60
  OP_CONNECT,
59
61
  OP_BIND,
@@ -349,6 +351,8 @@ VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
349
351
  VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value);
350
352
  VALUE um_shutdown(struct um *machine, int fd, int how);
351
353
  VALUE um_shutdown_async(struct um *machine, int fd, int how);
354
+ VALUE um_send_fd(struct um *machine, int sock_fd, int fd);
355
+ VALUE um_recv_fd(struct um *machine, int sock_fd);
352
356
 
353
357
  void um_async_op_set(VALUE self, struct um *machine, struct um_op *op);
354
358
  VALUE um_async_op_await(struct um_async_op *async_op);
@@ -373,6 +377,7 @@ VALUE um_queue_shift(struct um *machine, struct um_queue *queue);
373
377
 
374
378
  VALUE stream_get_line(struct um_stream *stream, VALUE buf, ssize_t maxlen);
375
379
  VALUE stream_get_string(struct um_stream *stream, VALUE buf, ssize_t len);
380
+ VALUE stream_skip(struct um_stream *stream, size_t len);
376
381
  VALUE resp_decode(struct um_stream *stream, VALUE out_buffer);
377
382
  void resp_encode(struct um_write_buffer *buf, VALUE obj);
378
383
  void resp_encode_cmd(struct um_write_buffer *buf, int argc, VALUE *argv);