ruby-trunk-changes r65937 - r65954

今日は Enumerator#+ と Enumerable#chain という複数の Enumerable/Enumerator を連結するメソッドの追加や、IO まわりの修正などがありました。

normal: r65937 2018-11-24 03:19:07 +0900

なんとなく r65931 と絡んでそうですが IO オブジェクトの finalizer でバッファを flush する fptr_finalize_flush() で race condition があって fptr->fd が -1 にクリアされた後で利用される可能性が残っているそうで io_close_fptr() から呼ばれる時に同じ fd に大して処理している thread へ通知したリストをみてそれらが抜けるのを待つ処理を fptr_finalize_flush() の中に移動しています。 もう関係ないですが thread.c に rb_thread_fd_close() っていう変更前の io_close_fptr() 内の処理に類似のがあるからこれでリファクタリングできたんじゃないかなぁ。まあこの変更でもうできなくなりましたが。

svn: r65938 2018-11-24 03:19:13 +0900

version.h の日付更新。

normal: r65939 2018-11-24 06:38:41 +0900

io_fd_check_closed() で IOError 例外発生前に rb_thread_check_ints() で割り込みチェックするようにしています。他の Thread が close した時の通知があった場合はそっちを先に処理しないと close した Thread が待ち続けてしまうのでそっちからの例外を先に処理すべきってことかな。ううーん、なんかスッキリしないですね。

normal: r65940 2018-11-24 07:01:35 +0900

r65939 と類似だと思いますが rb_wait_for_single_fd() でも RUBY_VM_CHECK_INTS_BLOCKING() を呼ぶところで context switch がおきて別 Thread で fd が閉じられている可能性があるので、内側のループで RUBY_VM_INTERRUPTED() の前に waiting_fds への追加をしていたのをもっと外側で行なって close の通知を受け取るようにしています。また大域脱出の発生時に waiting_fds に不正なポインタを残さないように EC_PUSH_TAG()/EC_POP_TAB() を追加しています。

svn: r65941 2018-11-24 07:01:38 +0900

r65940 のインデントのタブを空白に展開。

duerst: r65942 2018-11-24 08:18:47 +0900

common.mk で Unicode 用のデータファイルとして GraphemeBreakTest.txt という名前も追加しています。ファイル名の通り grapheme cluster の分割の仕様が記述されるファイルみたいで、正規表現の /\X/ や String#each_grapheme_cluster のテストに使うつもりとのこと。

k0kubun: r65943 2018-11-24 09:55:26 +0900

r65926 の Dir.home のテストの変更で "~username" の展開は Windows でうまく動かなかいそうで、Windows では単に "~" を File.expand_path で展開するようにしています。 https://github.com/ruby/ruby/pull/2022

samuel: r65944 2018-11-24 11:31:06 +0900

Fiber の coroutine 実装を Windows でも再度利用するように configure.ac を変更しています。AppVeyor での msys2 のビルトをチェックするため。

samuel: r65945 2018-11-24 11:31:11 +0900

coroutine/win64/Context.s で movaps 命令のオペランドの順序が逆転して逆にコピーしてしまっていたのを修正しています。

nobu: r65946 2018-11-24 13:33:59 +0900

common.mk の EXT_SRCS に ext/etc/constdefs.h を追加して make srcs-ext でこのヘッダを生成するようにしています。

nobu: r65947 2018-11-24 13:34:00 +0900

make cleans-srcs というターゲットを追加してビルドディレクトリの生成ソースファイルを削除するように、make realclean-srcs でソースディレクトリに生成されるソースファイルも削除するようにしています。さらに make realclean-srcs-extra で拡張ライブラリの生成ソース類も削除するようにしています。

normal: r65948 2018-11-24 17:23:26 +0900

fd の default non-blocking 化にともなって internal_read_func() で EAGAIN や EWOULDBLOCK で返ってきた時に select()/ppoll() などでイベント待ちして再度 read() するリトライを行うようにしています。あれこれって今までもやってたんじゃ? と思いますが、それは毎回 GVL を再取得していたので non-blocking な fd の場合は GVL 解放した状態でリトライを続けるようにしているのがミソみたいです。 この挙動をするかどうかの指定のために構造体 struct io_internal_read_struct に nonblock というメンバーが追加され、呼び元が nonblock な呼び出しかどうかで制御しています。あれでもたとえば io_read_nonblock() からの呼び出し時にフラグを立ててるけど、この時にイベント待ちしちゃだめなんじゃ……? [ruby-core:88305] [Bug #14968]

knu: r65949 2018-11-24 17:38:35 +0900

Enumerator#+ と Enumerable#chain というメソッドが追加されています。これは 2つ以上の Enumerable や Enumerator を順に連結してまとめて iterate する Enumerator::Chain という Enumerator を継承したクラスのオブジェクトを作って返すメソッドです。 Enumerator#+ は Enumerator::Chain のインスタンスを返すのでさらに繋げて (a + b + c) のようにも書けますね。 [ruby-core:89121] [Feature #15144]

knu: r65950 2018-11-24 17:38:36 +0900

NEWS ファイルに r65949 の Enumerator::Chain の追加について追記しています。

nobu: r65951 2018-11-24 19:29:23 +0900

Makefile.in の拡張子によるルールの定義で .s と .S のところを $(ASMEXT) を使うように変更しています。

samuel: r65952 2018-11-24 20:35:29 +0900

coroutine/* の配下にあるアセンブリソースファイルの拡張子を .s から大文字の .S に変更し ASMEXT も S に変更しています。

samuel: r65953 2018-11-24 20:35:34 +0900

チケットをみると checksec というコマンドでセキュリティチェックすると書き込みと実行の両方が可能な segment が含まれているという検出がされてしまうとのことで、coroutine/amd64/Context.S で .note.GNU-stack というセクションの保護ビットの設定を追加しています。

naruse: r65954 2018-11-24 20:53:19 +0900

String#grapheme_clusters の Enumerator で single_byte_optimizable() という関数で文字列の内容が 7bit ASCII のみだったらバイト単位の処理の関数を呼んで最適化していたのをやめています。 Unicode では CR+LF という 2 byte の改行コードを1つの文字として扱うそうなので、Encoding が Unicode 系である場合は内容が ASCII のみでもバイト単位で処理はできないとのこと。うーん、残念。 [ruby-core:90031] [Bug #15337]