Bug #7040
closedgem install で特定の gem がインストールできない
Description
trunk で特定の gem(例えば libv8等)をインストールしようとすると必ず失敗してしまいます。
% gem i libv8
ERROR: While executing gem ... (Zlib::BufError)
buffer error
Twitter 上で nagachika さんから Zlib の GVL 対応?が原因ではないかとコメントを頂きましたが、上記のエラー表示以降は調査しきれていません。
Files
Updated by nagachika (Tomoyuki Chikanaga) about 12 years ago
- Assignee set to drbrain (Eric Hodel)
Hello,
I'd like to switch to ruby-core, but I don't know how to do it on redmine...
Anyway, I've found that zstream_run_func() leaks Z_BUF_ERROR because inflate() could return Z_BUF_ERROR even when z->stream.avail_out > 0.
My tiny patch below prevent the exception, but I'm not confident at all it's right way to fix this issue.
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 6135e82..bcf289f 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -987,6 +987,7 @@ zstream_run_func(void *ptr)
if (z->stream.avail_out > 0) {
z->flags |= ZSTREAM_FLAG_IN_STREAM;
-
err = Z_OK; break; }
I think Eric (a.k.a drbrain) should have any idea, so I'll assign this ticket to him.
thakns,
Updated by nagachika (Tomoyuki Chikanaga) almost 12 years ago
- File zlib_inflate_buf_error.patch zlib_inflate_buf_error.patch added
- Category changed from core to ext
- Assignee changed from drbrain (Eric Hodel) to nagachika (Tomoyuki Chikanaga)
Hello,
I've investigated this little more deeper.
If inflate() (aka z->func->run()) return under condition which z->stream.avail_in == z->stream.avail_out == 0, current zstream_run_func() call inflate() once more even though there's no input available. In that case inflate() return Z_BUF_ERROR.
However, deflate() have hidden input buffer in z->stream.state (opaque structure) and should be called even when z->stream.avail_in == 0 (while z->stream.avail_out == 0).
I think zstream_run_func() should break from while loop when zstream->avail_in == 0 only if z->func->run == inflate.
I will commit an attached patch tomorrow if there's no objection.
ruby-dev なので日本語でも。
もう少し調べてみました。
zstream_run_func() で inflate() (z->func->run()) がたまたま入出力のバッファがぴったり空/一杯になった (z->stream.avail_in == z->stream.avail_out == 0) で返ってきた時に、今の実装だとバッファを拡張して再度 inflate() を呼んでしまいます。zlib は入力が既にない状態で inflate() を呼ぶと Z_BUF_ERROR を返すようです。
ただ deflate() の場合は不可視な z->stream->state の構造体の中に隠れたバッファを持っているようで、z->stream.avail_in == 0 でももう一度 deflate() を呼ぶ必要がある場合があるようです。
添付したパッチのように z->func->run が inflate の時に限り z->stream.avail_in == 0 の時にも zstream_run_func() の while ループから抜けて、余分に inflate() (z->func->run())を呼ばないようにしてはどうかと思います。 make test-all は手元の環境では通りました。
実際に gem がインストールできない問題で困っているということなので、特に反対がなければ明日にでもコミットしておこうと思います。
Updated by nagachika (Tomoyuki Chikanaga) almost 12 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r37119.
Hiroshi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
- ext/zlib/zlib.c (zstream_run_func): don't call inflate() when
z->stream.avail_in == 0. it return Z_BUF_ERROR.
but deflate() could be called with z->stream->avail_in == 0 because
it has hidden buffer in z->stream->state (opaque structure).
fix for gem install error. [ruby-dev:46149] [Bug #7040]