Skip to content

Commit 65e0ff8

Browse files
committed
Store console IO in Ractor-local storage
Ractor requires a shareable class has shareable constants only, but IO is not shareable unless frozen.
1 parent b1adc15 commit 65e0ff8

File tree

2 files changed

+70
-7
lines changed

2 files changed

+70
-7
lines changed

ext/io/console/console.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ getattr(int fd, conmode *t)
8181

8282
#define CSI "\x1b\x5b"
8383

84-
static ID id_getc, id_console, id_close;
84+
static ID id_getc, id_close;
8585
static ID id_gets, id_flush, id_chomp_bang;
8686

8787
#if defined HAVE_RUBY_FIBER_SCHEDULER_H
@@ -1566,6 +1566,56 @@ rb_io_closed_p(VALUE io)
15661566
}
15671567
#endif
15681568

1569+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1570+
#include "ruby/ractor.h"
1571+
static rb_ractor_local_key_t key_console_dev;
1572+
1573+
static bool
1574+
console_dev_get(VALUE klass, VALUE *dev)
1575+
{
1576+
return rb_ractor_local_storage_value_lookup(key_console_dev, dev);
1577+
}
1578+
1579+
static void
1580+
console_dev_set(VALUE klass, VALUE value)
1581+
{
1582+
rb_ractor_local_storage_value_set(key_console_dev, value);
1583+
}
1584+
1585+
static void
1586+
console_dev_remove(VALUE klass)
1587+
{
1588+
console_dev_set(klass, Qnil);
1589+
}
1590+
1591+
#else
1592+
1593+
static ID id_console;
1594+
1595+
static bool
1596+
console_dev_get(VALUE klass, VALUE *dev)
1597+
{
1598+
if (rb_const_defined(klass, id_console)) {
1599+
*dev = rb_const_get(klass, id_console);
1600+
return true;
1601+
}
1602+
return false;
1603+
}
1604+
1605+
static void
1606+
console_dev_set(VALUE klass, VALUE value)
1607+
{
1608+
rb_const_set(klass, id_console, value);
1609+
}
1610+
1611+
static void
1612+
console_dev_remove(VALUE klass)
1613+
{
1614+
rb_const_remove(klass, id_console);
1615+
}
1616+
1617+
#endif
1618+
15691619
/*
15701620
* call-seq:
15711621
* IO.console -> #<File:/dev/tty>
@@ -1594,10 +1644,9 @@ console_dev(int argc, VALUE *argv, VALUE klass)
15941644
// Force the class to be File.
15951645
if (klass == rb_cIO) klass = rb_cFile;
15961646

1597-
if (rb_const_defined(klass, id_console)) {
1598-
con = rb_const_get(klass, id_console);
1647+
if (console_dev_get(klass, &con)) {
15991648
if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
1600-
rb_const_remove(klass, id_console);
1649+
console_dev_remove(klass);
16011650
con = 0;
16021651
}
16031652
}
@@ -1606,7 +1655,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
16061655
if (sym == ID2SYM(id_close) && argc == 1) {
16071656
if (con) {
16081657
rb_io_close(con);
1609-
rb_const_remove(klass, id_console);
1658+
console_dev_remove(klass);
16101659
con = 0;
16111660
}
16121661
return Qnil;
@@ -1647,7 +1696,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
16471696
#ifdef CONSOLE_DEVICE_FOR_WRITING
16481697
rb_io_set_write_io(con, out);
16491698
#endif
1650-
rb_const_set(klass, id_console, con);
1699+
console_dev_set(klass, con);
16511700
}
16521701

16531702
if (sym) {
@@ -1769,11 +1818,15 @@ Init_console(void)
17691818
#endif
17701819

17711820
#undef rb_intern
1821+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1822+
key_console_dev = rb_ractor_local_storage_value_newkey();
1823+
#else
1824+
id_console = rb_intern("console");
1825+
#endif
17721826
id_getc = rb_intern("getc");
17731827
id_gets = rb_intern("gets");
17741828
id_flush = rb_intern("flush");
17751829
id_chomp_bang = rb_intern("chomp!");
1776-
id_console = rb_intern("console");
17771830
id_close = rb_intern("close");
17781831
#define init_rawmode_opt_id(name) \
17791832
rawmode_opt_ids[kwd_##name] = rb_intern(#name)

test/io/console/test_ractor.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,15 @@ def test_ractor
2020
end
2121
puts r.take
2222
end;
23+
24+
assert_in_out_err(%W[-r#{path}], "#{<<~"begin;"}\n#{<<~'end;'}", ["true"], [])
25+
begin;
26+
console = IO.console
27+
$VERBOSE = nil
28+
r = Ractor.new do
29+
IO.console
30+
end
31+
puts console.class == r.take.class
32+
end;
2333
end
2434
end if defined? Ractor

0 commit comments

Comments
 (0)