Bug #5217
closedlineno is broken when source code has about 7000 lines
Description
遠藤です。
asakusa.rb で出た話だそうですが (なひさんからの伝聞) 、soap4r と
simplecov を組み合わせると [BUG] bug が出るそうです。
いろいろ話を聞かせてもらった結果、以下のようにすると再現できました。
$ ruby -e 'puts "p\n" * 7000; puts "p([1"; puts "])"' > t.rb
$ cat t.rb
p
p
p
... 7000 行ほど p ...¶
p
p
$ ./ruby -rcoverage -e 'Coverage.start; load "t.rb"'
応急措置ですが、以下のパッチで直ります。
(rb_bug("bug") というアホメッセージは私の所業のようです。スミマセン)
害はないと思うので、これはこれでコミットしておこうと思います。
diff --git a/thread.c b/thread.c
index 6970d8f..57a6962 100644
--- a/thread.c
+++ b/thread.c
@@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
long line = rb_sourceline() - 1;
long count;
if (RARRAY_PTR(coverage)[line] == Qnil) {
-
rb_bug("bug");
-
}return;
count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
if (POSFIXABLE(count)) {
しかしそもそもの原因は、iseq のバイトコードの大きさが unsigned short
で管理されているために、バイトコードの大きさが 65536 を超えると行番号を
見失ってしまうという問題のような気がします。
私も最初勘違いしたのですが、行番号が 16 ビットという問題とは別であること
に注意。65536 行ほど大きくなくても 7000 行くらいで発症します。
これにより、rb_vm_get_sourceline の挙動が怪しくなっています。
これは coverage に限らず、
set_trace_func(proc {|type, file, line,| p line if type == "line" })
p
p
p
... 7000 行ほど p ...¶
p
p
p
というコードの出力が、
2
3
4
5
...
6550
6551
6552
6553
7001
7001
7001
7001
7001
...
となります。行番号が飛んでいることがわかります。
直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで
いるのは省メモリ化のためだと思いますので、これは既知の制限ということで
しょうか > ささださん
diff --git a/iseq.h b/iseq.h
index beeacbb..9c19501 100644
--- a/iseq.h
+++ b/iseq.h
@@ -44,9 +44,9 @@ struct rb_compile_option_struct {
};
struct iseq_insn_info_entry {
- unsigned short position;
- unsigned short line_no;
- unsigned short sp;
- unsigned long position;
- unsigned long line_no;
- unsigned long sp;
};
struct iseq_catch_table_entry {
--
Yuskue Endoh mame@tsg.ne.jp