Граф коммитов

372 Коммитов

Автор SHA1 Сообщение Дата
Nobuyoshi Nakada 50aac2ffd5
Share the size for sigaltstack between configure.ac and signal.c 2020-07-22 21:28:23 +09:00
Nobuyoshi Nakada eaa2de3112
Fixed a comment, wrong binary prefix [ci skip] 2020-07-11 15:21:12 +09:00
卜部昌平 de3e931df7 add UNREACHABLE_RETURN
Not every compilers understand that rb_raise does not return.  When a
function does not end with a return statement, such compilers can issue
warnings.  We would better tell them about reachabilities.
2020-06-29 11:05:41 +09:00
卜部昌平 b5eeb3453e trap_handler: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea.  Better refactor.
2020-06-29 11:05:41 +09:00
卜部昌平 224e9c3835 signm2signo: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea.  Better refactor.
2020-06-29 11:05:41 +09:00
卜部昌平 9e41a75255 sed -i 's|ruby/impl|ruby/internal|'
To fix build failures.
2020-05-11 09:24:08 +09:00
卜部昌平 d7f4d732c1 sed -i s|ruby/3|ruby/impl|g
This shall fix compile errors.
2020-05-11 09:24:08 +09:00
卜部昌平 9e6e39c351
Merge pull request #2991 from shyouhei/ruby.h
Split ruby.h
2020-04-08 13:28:13 +09:00
Yusuke Endoh 0256e4f0f5 thread_pthread.c: allocate sigaltstack before pthread_create
A new (not-initialized-yet) pthread attempts to allocate sigaltstack by
using xmalloc.  It may cause GC, but because the thread is not
initialized yet, ruby_native_thread_p() returns false, which leads to
"[FATAL] failed to allocate memory" and exit.

In fact, we can observe the error message in the log of OpenBSD CI:
https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20200306T083005Z.log.html.gz

This changeset allocates sigaltstack before pthread is created.
2020-03-06 21:41:34 +09:00
卜部昌平 5e22f873ed decouple internal.h headers
Saves comitters' daily life by avoid #include-ing everything from
internal.h to make each file do so instead.  This would significantly
speed up incremental builds.

We take the following inclusion order in this changeset:

1.  "ruby/config.h", where _GNU_SOURCE is defined (must be the very
    first thing among everything).
2.  RUBY_EXTCONF_H if any.
3.  Standard C headers, sorted alphabetically.
4.  Other system headers, maybe guarded by #ifdef
5.  Everything else, sorted alphabetically.

Exceptions are those win32-related headers, which tend not be self-
containing (headers have inclusion order dependencies).
2019-12-26 20:45:12 +09:00
Jeremy Evans c257303ae7 Deprecate rb_eval_cmd, add rb_eval_cmd_kw
rb_eval_cmd takes a safe level, and now that $SAFE is deprecated,
it should be deprecated as well.

Replace with rb_eval_cmd_kw, which takes a keyword flag.  Switch
the two callers to this function.
2019-11-18 01:00:25 +02:00
Jeremy Evans ffd0820ab3 Deprecate taint/trust and related methods, and make the methods no-ops
This removes the related tests, and puts the related specs behind
version guards.  This affects all code in lib, including some
libraries that may want to support older versions of Ruby.
2019-11-18 01:00:25 +02:00
Jeremy Evans c5c05460ac Warn on access/modify of $SAFE, and remove effects of modifying $SAFE
This removes the security features added by $SAFE = 1, and warns for access
or modification of $SAFE from Ruby-level, as well as warning when calling
all public C functions related to $SAFE.

This modifies some internal functions that took a safe level argument
to no longer take the argument.

rb_require_safe now warns, rb_require_string has been added as a
version that takes a VALUE and does not warn.

One public C function that still takes a safe level argument and that
this doesn't warn for is rb_eval_cmd.  We may want to consider
adding an alternative method that does not take a safe level argument,
and warn for rb_eval_cmd.
2019-11-18 01:00:25 +02:00
Nobuyoshi Nakada 29e6782f5d
Share ruby_sighandler_t definition 2019-10-09 23:39:58 +09:00
Yusuke Endoh 891cbd66a4 signal.c: save the original sighandlers for fatal signals
On Android, a signal handler that is not SIG_DFL is set by default for
SIGSEGV.  Ruby's install_sighandler inserts Ruby's handler only when the
signal has no handler, so it does not insert Ruby's SEGV report handler,
which caused some test failures.

This changeset forces to install Ruby's handler for some fatal signals
(sigbus, sigsegv, and sigill).  They keep the original handlers, and
call them when the interpreter receives the signals.
2019-10-09 23:22:15 +09:00
Yusuke Endoh dd477df411 error.c (rb_bug_for_fatal_signal): renamed from rb_bug_context
Just refactoring.

The name "rb_bug_context" is completely unclear for me.
(Can you see that "context" means "machine register context"?)
The context is available only when a fatal signal (sigbus, sigsegv, or
sigill) is received; in fact, the function is used only for fatal
signals.  So, I think the name should be changed.
2019-10-09 23:02:22 +09:00
Yusuke Endoh b9cf58d2b2 signal.c (ruby_abort): move the definition for refactoring
The three functions for fatal signals, sigbus, sigsegv, and sigill, are
a family.  The definition of ruby_abort had interrupted them for no
reason.  This change just moves the definition after the family.
2019-10-09 22:57:19 +09:00
Yusuke Endoh 170d154059 signal.c: Use MINSIGSTKSZ by casting to int
MINSIGSTKSZ is unsigned int in OpenBSD, which makes a warning of
comparison:

```
signal.c:535:14: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
    if (size < MINSIGSTKSZ)
        ~~~~ ^ ~~~~~~~~~~~
1 warning generated.
```
https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20191004T200009Z.log.html.gz
2019-10-05 07:37:19 +09:00
卜部昌平 0766f67168 move docs around [ci skip]
To properly generate documents.
2019-08-29 18:34:09 +09:00
卜部昌平 7b6fde4258 drop-in type check for rb_define_module_function
We can check the function pointer passed to rb_define_module_function
like how we do so in rb_define_method.  The difference is that this
changeset reveales lots of atiry mismatches.
2019-08-29 18:34:09 +09:00
Yusuke Endoh 8eee3f3a36 signal.c: Don't mark ruby_abort as NORETURN on Solaris
to suppress a warning.

```
signal.c: In function 'ruby_abort':
signal.c:987:1: warning: 'noreturn' function does return
 }
 ^
```
2019-08-27 13:59:13 +09:00
Nobuyoshi Nakada 0c2d81dada
Renamed ruby_finalize_{0,1}
And pass rb_execution_context_t as an argument.
2019-08-13 09:47:08 +09:00
git d2f8e03f34 * expand tabs. 2019-08-01 14:27:19 +09:00
Yusuke Endoh f45bb760fb signal.c: make signame_prefix a nul-terminated string
gcc 9.1.0 warns this.

```
signal.c:258:46: warning: '%.*s' directive argument is not a nul-terminated string [-Wformat-overflow=]
  258 |  rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'",
      |                                              ^~~~
  259 |    prefix, signame_prefix, vsig);
      |            ~~~~~~~~~~~~~~
signal.c:200:19: note: referenced argument declared here
  200 | static const char signame_prefix[3] = "SIG";
      |                   ^~~~~~~~~~~~~~
```
https://rubyci.org/logs/rubyci.s3.amazonaws.com/ubuntu/ruby-master/log/20190801T033009Z.log.html.gz
2019-08-01 14:25:15 +09:00
Jeremy Evans b1a2eddbfc Document acceptance of negative pid in Process.kill [ci skip]
Fixes [Bug #13501]
2019-07-26 08:13:34 -07:00
nobu de0ef1a9df [DOC] fix markups [ci skip]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67354 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-28 03:33:35 +00:00
nobu 98e65d9d92 Prefer rb_check_arity when 0 or 1 arguments
Especially over checking argc then calling rb_scan_args just to
raise an ArgumentError.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66238 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-06 07:49:24 +00:00
ko1 cdc614cd0a refactoring debug_counter.
* debug_counter.h: add comments for each counters.

* debug_counter.h: add some counters (see added comments for details).
  * obj_newobj
  * obj_newobj_slowpath
  * obj_newobj_wb_unprotected
  * obj_hash_empty
  * obj_hash_under4
  * obj_hash_ge4
  * obj_hash_ge8
  * heap_xmalloc
  * heap_xrealloc
  * heap_xfree

* gc.c: add some debug counters (see the above list).

* debug_counter.c (rb_debug_counter_show_results): accept
  a header message.

* signal.c (ruby_default_signal): show debug counter results
  and malloc info (rb_malloc_info_show_results()) before
  SIGNAL exit.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64841 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-25 18:13:29 +00:00
nobu 55c7b8541a Fix for old names of mcontext registers
c.f. https://github.com/mistydemeo/tigerbrew/issues/473

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64812 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-22 20:13:08 +00:00
svn 2def52500f * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64807 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-21 10:19:14 +00:00
nobu 7e9ee35fb8 Remove -Wno-parentheses flag.
[Fix GH-1958]

From: Jun Aruga <jaruga@redhat.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64806 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-21 10:19:10 +00:00
nobu 67dba250e8 signal.c: consider non-sigaltstack platforms
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64673 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-09-10 09:35:03 +00:00
naruse 682a661e1c Re-Revert "Temporary revert "process.c: dead code when no SIGCHLD""
This re-reverts commit r64447.
The issue was machine side problem.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64493 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-21 13:39:24 +00:00
naruse b5b5b28c65 Temporary revert "process.c: dead code when no SIGCHLD"
This reverts commit r64407.
Maybe it breaks http://mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-trunk/log/20180817T095734Z.fail.html.gz

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64447 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18 12:35:28 +00:00
normal fe2f89af9a thread.c (sleep_*): reduce the effect of spurious interrupts
Spurious interrupts from SIGCHLD cause Mutex#sleep (via
ConditionVariable#wait) to return early and breaks some use
cases.  Since these are outside the programs's control with
MJIT, we will only consider pending interrupts (e.g. those
from Thread#run) and signals which cause a Ruby-level Signal.trap
handler to fire as "spurious" wakeups.

[ruby-core:88537] [Feature #15002]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-18 09:07:36 +00:00
nobu 3bd2d01f96 process.c: dead code when no SIGCHLD
* process.c (ruby_waitpid_all): nothing to do unless SIGCHLD is
  available.

* signal.c (ruby_nocldwait): used only if SIGCHLD is available.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-17 05:59:45 +00:00
nobu 028cda35c7 signal.c: no SIGCHLD, no sigchld_hit
* signal.c (sigchld_hit): if SIGCHLD is not available, this variable
  never sets.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64402 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-17 01:39:49 +00:00
normal 48b6bd74e2 thread_pthread.c: eliminate timer thread by restructuring GVL
This reverts commit 194a6a2c68 (r64203).

Race conditions which caused the original reversion will be fixed
in the subsequent commit.

[ruby-core:88360] [Misc #14937]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64352 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-13 21:34:20 +00:00
normal 194a6a2c68 thread_pthread.c: restore timer-thread for now :<
[ruby-core:88306]

Revert "process.c: ensure th->interrupt lock is held when migrating"

This reverts commit 5ca416bdf6 (r64201)

Revert "process.c (rb_waitpid): reduce sigwait_fd bouncing"

This reverts commit 217bdd776f (r64200).

Revert "test/ruby/test_thread.rb (test_thread_timer_and_interrupt): add timeouts"

This reverts commit 9f395f1120 (r64199).

Revert "thread_pthread.c (native_sleep): reduce ppoll sleeps"

This reverts commit b3aa256c4d (r64193).

Revert "thread.c (consume_communication_pipe): do not retry after short read"

This reverts commit 291a82f748 (r64185).

Revert "test/ruby/test_io.rb (test_race_gets_and_close): timeout each thread"

This reverts commit 3dbd8d1f66 (r64184).

Revert "thread_pthread.c (gvl_acquire_common): persist timeout across calls"

This reverts commit 8c2ae6e3ed (r64165).

Revert "test/ruby/test_io.rb (test_race_gets_and_close): use SIGABRT on timeout"

This reverts commit 931cda4db8 (r64135).

Revert "thread_pthread.c (gvl_yield): do ubf wakeups when uncontended"

This reverts commit 508f00314f (r64133).

Revert "thread_pthread.h (native_thread_data): split condvars on some platforms"

This reverts commit a038bf238b (r64124).

Revert "process.c (waitpid_nogvl): prevent conflicting use of sleep_cond"

This reverts commit 7018acc946 (r64117).

Revert "thread_pthread.c (rb_sigwait_sleep): th may be 0 from MJIT"

This reverts commit 56491afc79 (r64116).

Revert "thread*.c: waiting on sigwait_fd performs periodic ubf wakeups"

This reverts commit ab47a57a46 (r64115).

Revert "thread_pthread.c (gvl_destroy): make no-op on GVL bits"

This reverts commit 95cae74817 (r64114).

Revert "thread_pthread.c (rb_sigwait_sleep): fix uninitialized poll set in UBF case"

This reverts commit 4514362948 (r64113).

Revert "thread_pthread.c (rb_sigwait_sleep): re-fix [Bug #5343] harder"

This reverts commit 26b8a70bb3 (r64111).

Revert "thread.c: move ppoll wrapper into thread_pthread.c"

This reverts commit 3dc7727d22 (r64110).

Revert "thread.c: move ppoll wrapper before thread_pthread.c"

This reverts commit 2fa1e2e3c3 (r64109).

Revert "thread_pthread.c (ubf_select): refix [Bug #5343]"

This reverts commit 4c1ab82f06 (r64108).

Revert "thread_win32.c: suppress warnings by -Wsuggest-attribute"

This reverts commit 6a9b63e390 (r64159).

Revert "thread_pthread: remove timer-thread by restructuring GVL"

This reverts commit 708bfd2115 (r64107).

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64203 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-08-06 05:22:00 +00:00
normal 708bfd2115 thread_pthread: remove timer-thread by restructuring GVL
To reduce resource use and reduce CI failure; remove
timer-thread.  Single-threaded Ruby processes (including forked
children) will never see extra thread overhead.  This prevents
glibc and jemalloc from going into multi-threaded mode and
initializing locks or causing fragmentation via arena explosion.

The GVL is implements its own wait-queue as a ccan/list to
permit controlling wakeup order.  Timeslice under contention is
handled by a designated timer thread (similar to choosing a
"patrol_thread" for current deadlock checking).

There is only one self-pipe, now, as wakeups for timeslice are
done independently using condition variables.  This reduces FD
pressure slightly.

Signal handling is handled directly by a Ruby Thread (instead
of timer-thread) by exposing signal self-pipe to callers of
rb_thread_fd_select, native_sleep, rb_wait_for_single_fd, etc...
Acquiring, using, and releasing the self-pipe is exposed via 4
new internal functions:

1) rb_sigwait_fd_get - exclusively acquire timer_thread_pipe.normal[0]

2) rb_sigwait_fd_sleep - sleep and wait for signal (and no other FDs)

3) rb_sigwait_fd_put - release acquired result from rb_sigwait_fd_get

4) rb_sigwait_fd_migrate - migrate signal handling to another thread
                           after calling rb_sigwait_fd_put.

rb_sigwait_fd_migrate is necessary for waitpid callers because
only one thread can wait on self-pipe at a time, otherwise a
deadlock will occur if threads fight over the self-pipe.

TRAP_INTERRUPT_MASK is now set for the main thread directly in
signal handler via rb_thread_wakeup_timer_thread.

Originally, I wanted to use POSIX timers
(timer_create/timer_settime) for this.  Unfortunately, this
proved unfeasible as Mutex#sleep resumes on spurious wakeups and
test/thread/test_cv.rb::test_condvar_timed_wait failed.  Using
pthread_sigmask to mask out SIGVTALRM fixed that test,  but
test/fiddle/test_function.rb::test_nogvl_poll proved there'd be
some unavoidable (and frequent) incompatibilities from that
approach.

Finally, this allows us to drop thread_destruct_lock and
interrupt current ec directly.

We don't need to rely on vm->thread_destruct_lock or a coherent
vm->running_thread on any platform.  Separate timer-thread for
time slice and signal handling is relegated to thread_win32.c,
now.

[ruby-core:88088] [Misc #14937]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-29 20:47:33 +00:00
normal b93dc84883 signal.c: preserve trap(:CHLD, "IGNORE") behavior with SIGCHLD
We need to preserve "IGNORE" behavior from Ruby 2.5 and earlier.
We can't rely on SA_NOCLDWAIT any more, since we always need
system() and MJIT to work; so we fake that behavior using
dedicated reaper (currently in timer-thread).

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63879 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-08 00:02:27 +00:00
normal 44fc3d08eb unrevert r63852 but keep SIGCHLD path disabled for win32
Reading win32/win32.c waitpid implementation, maybe waitpid(-1, ...)
on that platform will never conflict with mjit use of waitpid.

In any case, I've added WAITPID_USE_SIGCHLD macro to vm_core.h
so it can be easy for Linux/BSD users to test (hopefully!)
win32-compatible code.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-05 03:02:33 +00:00
nobu b3799b93c2 signal.c: packed signals
* signal.c (signals): pack signal names instead of references.

* signal.c (signm2signo): also reject too long signal name.
  [ruby-core:87767] [Bug #14893]

reapply r63841 and r63842, which are unrelated to r63758 but had been
wrongly reverted by r63852.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63854 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-04 16:10:14 +00:00
naruse df4a126d65 Revert r63758 and related commits
The change is unstable on Windows. Please re-commit it when it correctly
supports Windows.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-04 15:08:56 +00:00
kazu 60fa7d5fa3 Fix compile error
signal.c:69:10: error: variably modified ‘signm’ at file scope
     char signm[LONGEST_SIGNAME + 1];
          ^

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-03 15:25:49 +00:00
nobu a0e141b34f signal.c: packed signals
* signal.c (signals): pack signal names instead of references.

* signal.c (signm2signo): also reject too long signal name.
  [ruby-core:87767] [Bug #14893]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63841 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-03 13:34:56 +00:00
normal ce2a3b40ed use SIGCHLD_LOSSY to enable waitpid polling mode
Some systems lack SIGCHLD or have incomplete SIGCHLD
implementations.  So enable polling mode for them.

[ruby-core:87705] [Bug #14867]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-30 00:51:57 +00:00
normal 4bf8834dc8 signal.c: use ATOMIC_EXCHANGE for sigchld_hit
sig_atomic_t may not be sufficient for multi-threaded
applications if the sighandler runs on a different CPU
than timer thread.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63793 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-29 22:13:02 +00:00
normal 8222d794f3 signal.c: fix braino in fake_grantfd
[Bug #14871]

Is neon down?  I missed ruby-core notifications on this.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-27 08:24:10 +00:00
normal 054a412d54 hijack SIGCHLD handler for internal use
Use a global SIGCHLD handler to guard all callers of rb_waitpid.
To work safely with multi-threaded programs, we introduce a
VM-wide waitpid_lock to be acquired BEFORE fork/vfork spawns the
process.  This is to be combined with the new ruby_waitpid_locked
function used by mjit.c in a non-Ruby thread.

Ruby-level SIGCHLD handlers registered with Signal.trap(:CHLD)
continues to work as before and there should be no regressions
in any existing use cases.

Splitting the wait queues for PID > 0 and groups (PID <= 0)
ensures we favor PID > 0 callers.

The disabling of SIGCHLD in rb_f_system is longer necessary,
as we use deferred signal handling and no longer make ANY
blocking waitpid syscalls in other threads which could "beat"
the waitpid call made by rb_f_system.

We prevent SIGCHLD from firing in normal Ruby Threads and only
enable it in the timer-thread, to prevent spurious wakeups
from in test/-ext-/gvl/test_last_thread.rb with MJIT enabled.

I've tried to guard as much of the code for RUBY_SIGCHLD==0
using C "if" statements rather than CPP "#if" so to reduce
the likelyhood of portability problems as the compiler will
see more code.

We also work to suppress false-positives from
Process.wait(-1, Process::WNOHANG) to quiets warnings from
spec/ruby/core/process/wait2_spec.rb with MJIT enabled.

Lastly, we must implement rb_grantpt for ext/pty.  We need a
MJIT-compatible way of supporting grantpt(3) which may spawn
the `pt_chown' binary and call waitpid(2) on it.

[ruby-core:87605] [Ruby trunk Bug#14867]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-27 03:14:30 +00:00