[#45703] test_advise failure on GNU/Linux — Tanaka Akira <tanaka.akira@...>
今朝、気がついたのですが、手元で test_advise が失敗します。
小崎です
>> /tmp は tmpfs で、カレントディレクトリは ext3 なのですが、
2012年6月22日 16:42 KOSAKI Motohiro <kosaki.motohiro@gmail.com>:
[#45723] Developers' meeting (7/21) — Yusuke Endoh <mame@...>
Hello, committers
Four seats are now left.
[#45735] [ruby-trunk - Feature #6587][Open] proposal: adding new methods File.rootname and Pathname#rootname — "usa (Usaku NAKAMURA)" <usa@...>
[#45745] Re: [ruby-changes:24028] yugui:r36079 (trunk): Embedding CRuby interpreter without internal headers has been difficult — SASADA Koichi <ko1@...>
見逃していました.
2012/6/15 SASADA Koichi <ko1@atdot.net>:
ささだです.
2012/6/15 SASADA Koichi <ko1@atdot.net>:
ささだです.
2012/6/19 SASADA Koichi <ko1@atdot.net>:
こんにちは、なかむら(う)です。
2012/6/15 U.Nakamura <usa@garbagecollect.jp>:
なかだです。
[#45769] [ruby-trunk - Bug #6606][Open] default_external encoding and STDOUT and UTF-8 — "shyouhei (Shyouhei Urabe)" <shyouhei@...>
[#45780] Re: [ruby-changes:24083] nobu:r36134 (trunk): process.c: no method calls in async-signal-safe — Tanaka Akira <akr@...>
2012/6/19 nobu <ko1@atdot.net>:
[#45794] :new_pgroup and :pgroup option for spawn. — Tanaka Akira <akr@...>
process.c で気がついたのですが、spawn に Windows 用の :new_pgroup というオプションが
こんにちは、なかむら(う)です。
2012年6月25日 11:27 U.Nakamura <usa@garbagecollect.jp>:
こんにちは、なかむら(う)です。
2012年6月25日 11:52 U.Nakamura <usa@garbagecollect.jp>:
こんにちは、なかむら(う)です。
2012年6月25日 12:13 U.Nakamura <usa@garbagecollect.jp>:
こんにちは、なかむら(う)です。
[#45818] [ruby-trunk - Feature #6643][Open] io.seek(off, :end) — "akr (Akira Tanaka)" <akr@...>
At Mon, 25 Jun 2012 19:32:06 +0900,
2012年6月25日 23:37 SATOH Fumiyasu <fumiyas@osstech.jp>:
[#45826] Question: Thread#kill doesn't throw Exception — SASADA Koichi <ko1@...>
ささだです.
> さらに突っ込んだ質問:
(2012/06/26 4:25), KOSAKI Motohiro wrote:
[ruby-dev:45761] Re: [ruby-changes:24028] yugui:r36079 (trunk): Embedding CRuby interpreter without internal headers has been difficult
ささだです.
(2012/06/15 22:02), Yugui wrote:
> コンパイルコストが本当に必要になるケースがはっきりしてくるまでは、まずはそれで良いかもしれません。
> じゃ、ruby_compile_main_from_string と ruby_eval_main は削除しましょう。
>
> ここで案が2つあります。
> 1. toplevel_binding と rb_f_evalを公開する
> 2. さらに両者を合わせてruby_eval_in_main みたいなのを作る。
>
> どっちが良いと思います?
> ちなみに、いずれにしてもさらにファイル版は必要だと思います。というのはマジックコメントとか読んで
> 適切なエンコーディングを付けたりってのは結構面倒なので。
> で、そのエンコーディングを付ける話を始めるとまたencdet話に跳んでしまうので、
> * rb_eval_string_in_main
> * rb_eval_file_in_main
> を作るのが現実的かなと思ってます。
返事が遅くなってすみません.長いメールになりましたが,ちゃんと議論しよ
うとすると,こういうふうにまとめないといかんと思って,それで面倒がって遅
れておりました.すみません.
中田さんに協力してもらって,現在,Ruby を組み込んだアプリから Ruby プ
ログラムを実行する方法をまとめました.下記に示すように意外とある,という
か,あまり一貫性がなく追加しているので,あまり良くないなぁと,思っている
というのがありまして,なので慎重になっている次第です.
プログラムを組み込んだアプリから指定して実行する,という時,気にしない
といけない点がいくつかあるかと思います.次の 5 項目としてまとめました.
(a) プログラムの文字列はどうやって渡すか?
(b) トップレベルの self はどうなるか?
(c) 実行バインディングはどうなるか?
(d) __FILE__ はどうなるか?
(e) エンコーディングはどうなるか?
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
(1) ruby_options() を利用(-r,-e,ファイル名を指定,標準入力から入力)
ruby(1) と同じ利用感が得られます.
-e は,エンコーディングは下記のようになるようです.
http://jp.rubyist.net/magazine/?0025-Ruby19_m17n
> なお、標準入力から読み込んだスクリプトや、コマンドラインオプション -e
で与えたスクリプトの場合は、magic comment がなかった場合、ロケールが
script encoding として用いられます。このため、1 行スクリプトを書く場合に
までいちいち magic comment を書く必要はありません。
プログラムの __FILE__ を好き勝手に指定する方法はありません(勝手に決ま
ります).-r,ファイル名指定では,それぞれ読み込んだファイルの名前,-e
では,"-e" になります.
まとめますと,
(a) プログラムの文字列はどうやって渡すか?
-r:ファイル名でファイルを指定(ファイルの中身がプログラム)
-e:実行する文字列を C 文字列で指定
ファイル名:ファイル名でファイルを指定(ファイルの中身がプログラム)
標準入力から:標準入力から読む
(b) トップレベルの self はどうなるか?
main になる(ruby -e self で得られるオブジェクトを,ここでは main と呼
ぶことにします).
(c) 実行バインディングはどうなるか?
-r:新しいバインディングを作って実行します.
例えば,ruby -rfoo -e 'p a' とあって,foo.rb に a=1 とあったとして
も,-r と -e は別々の環境を指しているので -e で a が見つからないというエ
ラーになります.
それ以外:
TOPLEVEL_BINDING になります.
例えば,ruby -e 'a=1' -e 'p a' とすると,プログラムが 2 回実行されます
が,同じバインディングを共有しているため,問題無く2回目の実行で 1 が出力
されます.
(d) __FILE__ はどうなるか?
下記に固定されます.
-r:指定されたファイル名
-e:"-e"
ファイル名:ファイル名
標準入力から:"-"
(e) エンコーディングはどうなるか?
マジックコメントを見て判断.ただし,下記の例外があり.
http://jp.rubyist.net/magazine/?0025-Ruby19_m17n
> なお、標準入力から読み込んだスクリプトや、コマンドラインオプション -e
で与えたスクリプトの場合は、magic comment がなかった場合、ロケールが
script encoding として用いられます。このため、1 行スクリプトを書く場合に
までいちいち magic comment を書く必要はありません。
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
構文エラー,実行時エラー,ともにエラーが起きたらバックトレースを標準エ
ラー出力に表示して終了します.
(2) VALUE rb_eval_string(const char *str)
VALUE rb_eval_string_protect(const char *str, int *state)
VALUE rb_eval_string_wrap(const char *str, int *state)
eval という名前ですが,意に反して,実は Kernel.eval ではありません.判
りづらいですね.これがまさに,Ruby を組み込んだアプリから使うことを意識
して作ったインターフェースです.多分.
str で指定された C 文字列を実行します.-e に似ています.ただし,実行コ
ンテキストは TOPLEVEL_BINDING ではありません.self は main です.これ
は,require された時のコンテキストと同じです.
__FILE__ は "(eval)" 固定です.
protect は,例外が起きたとき,外に例外が伝搬しません.state にどういう
実行状態で止まったか,ということが入ります.
wrap は,protect の機能に加えて,load で第2引数を true にしたときに
toplevel に匿名 module が指定されますが,それと同じ挙動を行います.
実は,yugui さんが欲しいのは,__FILE__ が指定出来ない,という点以外は
これなんじゃないかと思うのですが,どうでしょうか.TOPLEVEL_BINDING で実
行したい,というのは,本当に必要な要件なんでしょうか.
まとめます.
(a) プログラムの文字列はどうやって渡すか?
C 文字列で渡します.
(b) トップレベルの self はどうなるか?
main になります.
(c) 実行バインディングはどうなるか?
新しい binding を作って実行します.require で新しく作られるバインディ
ングと同じです.
rb_eval_string_wrap() の場合,定数のトップレベルが匿名モジュールになり
ます.
(d) __FILE__ はどうなるか?
"(eval)" になります.
(e) エンコーディングはどうなるか?
マジックコメントを見ます.
(無いとどうなんだろう...)
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
VALUE rb_eval_string(const char *str)
外側に伝搬します.アプリ側でトラップ出来るようにしておかないと死にます.
VALUE rb_eval_string_protect(const char *str, int *state)
VALUE rb_eval_string_wrap(const char *str, int *state)
エラーが起きたら state に 0 以外の値が入っています.
(3) void rb_load(VALUE fname, int wrap)
void rb_load_protect(VALUE fname, int wrap, int *state)
ファイル名を String で渡す,ということ以外は (2) と変わりません.
(a) プログラムの文字列はどうやって渡すか?
ファイル名でファイルを指定(ファイルの中身がプログラム).
(b) トップレベルの self はどうなるか?
main になります.wrap が !0 の場合,定数のトップレベルが匿名モジュール
になります.
(c) 実行バインディングはどうなるか?
新しい binding を作って実行します.require で新しく作られるバインディ
ングと同じです.
(d) __FILE__ はどうなるか?
渡されたファイル名と同じになります(多分).
(e) エンコーディングはどうなるか?
マジックコメントを見ます.
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
void rb_load(VALUE fname, int wrap)
外側に伝搬します.設定していないと死にます(多分).
void rb_load_protect(VALUE fname, int wrap, int *state)
ここで食い止めます.state を見るとエラーの有無をチェック出来ます.
(4) その他
その他,Kernel.eval,Kernel.instance_eval,Kernel.class_eval などを用
いる,という手段もありますが,どちらかというと拡張ライブラリから呼び出す
ような手段であり,設定も面倒なので省略します.いや,それらで済むのなら,
それでいいのですが.
ruby.h などで非公開の関数ですが rb_iseq_compile() + rb_iseq_eval() と
いうのもあるかと思ったんですが,よくよく調べてみると,これらをきちんと使
うのは準備が大変だということがわかりました.
なお,上記で「準備しないと死ぬ」とあるのは,例外の伝搬先が設定されてい
ないと死ぬ,という感じです.普通に組込み用途でカジュアルに使わない方がい
いですね.
とりあえず,現状認識はこの通りです.
では,yugui さんご提案のインターフェースを見てます.
> * rb_eval_string_in_main
> * rb_eval_file_in_main
(a) プログラムの文字列はどうやって渡すか?
不明.C 文字列だろうか.
(b) トップレベルの self はどうなるか?
main です.
(c) 実行バインディングはどうなるか?
TOPLEVEL_BINDING です.
(d) __FILE__ はどうなるか?
不明.引数で渡すんだろうか.
(e) エンコーディングはどうなるか?
多分,プログラム文字列に書いてあるのを読むんじゃないかと思う.
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
不明.
ちなみに,組込みで有名な mruby さんのインターフェースを調べてみます.
int mrb_compile_file(mrb_state*,FILE*);
int mrb_compile_string(mrb_state*,char*);
int mrb_compile_nstring(mrb_state*,char*,size_t);
ぱっと見た感じ,ファイルや C 文字列を渡すと,これらの関数は返値 n を返
し,コンパイル結果が mrb_state->ipre[n] に格納されます.
mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
そして,mrb_run で,格納されたコンパイル結果を実行しています(多分).
第二引数に,コンパイル結果 mrb_state->irep[n] を mrb_proc_new() に渡して
Proc オブジェクトを作って(多分),第三引数にその Proc の初期値を渡して
実行,という感じでしょうか.多分.違ってたらすみません.
まとめます.
(a) プログラムの文字列はどうやって渡すか?
C 文字列や FILE*.
(b) トップレベルの self はどうなるか?
どうなんだろう,これ.サンプル見ても判らなかったんだけど,main が勝手
に入るのかなぁ.
(c) 実行バインディングはどうなるか?
そもそも binding が存在しません.
(d) __FILE__ はどうなるか?
どうなるんでしょうか? そもそもあるの?
$ bin/mruby -e 'p __FILE__'
"(null)"
$ bin/mruby t.rb # t.rb には p __FILE__ と書いてある
"t.rb"
あるようでした.いつの間に設定されてたんだろう.mrb_compile_* だと,何が
入るんだろう.
(e) エンコーディングはどうなるか?
エンコーディングが存在しません(多分.あったらすみません)
(f) エラーが起きたらどうなるか?(構文エラー,実行時エラー)
どうなるんでしょう? mrb_run() の外まで伝搬するのかなぁ.
これでサーベイを終わります.JRuby とかも調べ出すといいんでしょうが,
ちょっとしんどくなってきました.
こう見ると,VALUE rb_eval_string_protect(const char *str, int *state)
が,__FILE__ を指定出来ない(そして名前が Kernel.eval を想起させる悪い名
前である),という点以外はいけてるんじゃないかと思うのですが,どうでしょ
うか.
アプリケーション組込みアプリが,TOPLEVEL_BINDING 上で動作する,という
のは,実は想定していませんでした(なので無かった).require 相当が動けば
いいと思っていました.
やりたいときは,
$exec_string にプログラムをセットしてから,
rb_eval_string_protected("eval($exec_string, TOPLEVEL_BINDING)"...);
なんて手もあるかもしれません,がそれはあんまりかな.
--
// SASADA Koichi at atdot dot net