Skip to content

Commit 9d78fc3

Browse files
committed
Implement UM#waitpid
1 parent a25f2d1 commit 9d78fc3

File tree

7 files changed

+74
-14
lines changed

7 files changed

+74
-14
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
- Add `#pipe`
1+
- Add `#waitpid`
2+
- Add `UM.pipe`, `UM.kernel_version`
23
- Add `#open`
34
- Fix `#spin`
45
- Fix handling of signal interruption.

TODO.md

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
- statx
88
- link / linkat / unlink / unlinkat / symlink
99
- rename / renameat
10-
- waitid
1110
- fadvise
1211
- madvise
1312
- getxattr / setxattr

ext/um/um.c

+18
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,24 @@ VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
513513
return raise_if_exception(ret);
514514
}
515515

516+
VALUE um_waitpid(struct um *machine, int pid, int options) {
517+
struct um_op op;
518+
um_prep_op(machine, &op, OP_BIND);
519+
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
520+
521+
siginfo_t infop;
522+
io_uring_prep_waitid(sqe, P_PID, pid, &infop, options, 0);
523+
524+
VALUE ret = um_fiber_switch(machine);
525+
if (um_check_completion(machine, &op))
526+
ret = INT2NUM(op.result.res);
527+
528+
RB_GC_GUARD(ret);
529+
raise_if_exception(ret);
530+
531+
return rb_ary_new_from_args(2, INT2NUM(infop.si_pid), INT2NUM(infop.si_status));
532+
}
533+
516534
/*******************************************************************************
517535
multishot ops
518536
*******************************************************************************/

ext/um/um.h

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ VALUE um_read_each(struct um *machine, int fd, int bgid);
193193
VALUE um_write(struct um *machine, int fd, VALUE str, int len);
194194
VALUE um_close(struct um *machine, int fd);
195195
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
196+
VALUE um_waitpid(struct um *machine, int pid, int options);
196197

197198
VALUE um_accept(struct um *machine, int fd);
198199
VALUE um_accept_each(struct um *machine, int fd);

ext/um/um_class.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -272,13 +272,18 @@ VALUE UM_open_ensure(VALUE arg) {
272272
VALUE UM_open(VALUE self, VALUE pathname, VALUE flags) {
273273
struct um *machine = get_machine(self);
274274
// TODO: take optional perm (mode) arg
275-
VALUE ret = um_open(machine, pathname, NUM2INT(flags), 0666);
275+
VALUE fd = um_open(machine, pathname, NUM2INT(flags), 0666);
276276
if (rb_block_given_p()) {
277-
struct um_open_ctx ctx = { self, ret };
278-
return rb_ensure(rb_yield, ret, UM_open_ensure, (VALUE)&ctx);
277+
struct um_open_ctx ctx = { self, fd };
278+
return rb_ensure(rb_yield, fd, UM_open_ensure, (VALUE)&ctx);
279279
}
280280
else
281-
return ret;
281+
return fd;
282+
}
283+
284+
VALUE UM_waitpid(VALUE self, VALUE pid, VALUE options) {
285+
struct um *machine = get_machine(self);
286+
return um_waitpid(machine, NUM2INT(pid), NUM2INT(options));
282287
}
283288

284289
VALUE UM_pipe(VALUE self) {
@@ -322,6 +327,8 @@ void Init_UM(void) {
322327
rb_define_method(cUM, "sleep", UM_sleep, 1);
323328
rb_define_method(cUM, "write", UM_write, -1);
324329

330+
rb_define_method(cUM, "waitpid", UM_waitpid, 2);
331+
325332
rb_define_method(cUM, "accept", UM_accept, 1);
326333
rb_define_method(cUM, "accept_each", UM_accept_each, 1);
327334
rb_define_method(cUM, "bind", UM_bind, 3);

ext/um/um_const.c

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "ruby.h"
22

33
#include <fcntl.h>
4+
#include <sys/wait.h>
45

56
#include <arpa/inet.h>
67
#include <sys/types.h>
@@ -32,6 +33,14 @@ void um_define_net_constants(VALUE mod) {
3233
DEF_CONST_INT(mod, O_TRUNC);
3334
DEF_CONST_INT(mod, O_WRONLY);
3435

36+
DEF_CONST_INT(mod, WNOHANG);
37+
DEF_CONST_INT(mod, WUNTRACED);
38+
DEF_CONST_INT(mod, WCONTINUED);
39+
DEF_CONST_INT(mod, WEXITED);
40+
DEF_CONST_INT(mod, WSTOPPED);
41+
DEF_CONST_INT(mod, WCONTINUED);
42+
DEF_CONST_INT(mod, WNOWAIT);
43+
3544
DEF_CONST_INT(mod, SOCK_STREAM);
3645
DEF_CONST_INT(mod, SOCK_DGRAM);
3746
DEF_CONST_INT(mod, SOCK_RAW);

test/test_um.rb

+33-8
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,11 @@ def test_open_with_block
992992
assert_raises(Errno::EBADF) { machine.close(res) }
993993
assert_equal 'bar', IO.read(PATH)
994994
end
995+
996+
def test_open_bad_arg
997+
assert_raises(Errno::ENOENT) { machine.open(PATH, UM::O_RDONLY) }
998+
assert_raises(Errno::ENOENT) { machine.open(PATH, UM::O_RDONLY) {} }
999+
end
9951000
end
9961001

9971002
class PipeTest < UMBaseTest
@@ -1014,11 +1019,31 @@ def test_pipe
10141019
end
10151020
end
10161021

1017-
# class WaitIDTest < UMBaseTest
1018-
# def test_waitid
1019-
# rfd, wfd = UM.pipe
1020-
# pid = fork do
1021-
# exit 42
1022-
# end
1023-
# end
1024-
# end
1022+
class WaitTest < UMBaseTest
1023+
def test_waitpid
1024+
msg = 'hello from child'
1025+
1026+
rfd, wfd = UM.pipe
1027+
pid = fork do
1028+
m = UM.new
1029+
m.write(wfd, msg)
1030+
m.close(wfd)
1031+
exit 42
1032+
end
1033+
1034+
ret = machine.waitpid(pid, UM::WEXITED)
1035+
assert_kind_of Array, ret
1036+
assert_equal [pid, 42], ret
1037+
1038+
buf = +''
1039+
ret = machine.read(rfd, buf, 8192)
1040+
assert_equal msg.bytesize, ret
1041+
assert_equal msg, buf
1042+
end
1043+
1044+
def test_waitpid_bad_pid
1045+
assert_raises(Errno::ECHILD) { machine.waitpid(1, UM::WEXITED) }
1046+
end
1047+
1048+
end
1049+

0 commit comments

Comments
 (0)