From: "akr (Akira Tanaka)" Date: 2013-07-18T23:02:07+09:00 Subject: [ruby-dev:47528] [ruby-trunk - Bug #8644] valgrind error in a readline test Issue #8644 has been updated by akr (Akira Tanaka). File readline-fix-invalid-read.patch added とりあえず、close されたかどうかは元々の IO オブジェクトが close されたかどうかで判断するようなパッチを書いてみたんですが、 どうですかね。 なお、やってみて気がついたのですが、 isatty して EBADF になることを確認するというコードがあって、 しかも Readline.readline のドキュメントにその挙動が * Raises IOError exception if below conditions are satisfied. * 1. stdin is not tty. * 2. stdin was closed. (errno is EBADF after called isatty(2).) と明記されているのですが、 そもそも EBADF を検査するのは間違っている (常に他のスレッドや signal handler が fd を open する可能性はあるので確実でない) というのと、 実際に isatty で tty でないときに IOError にしてみたら、 テストが失敗しまくる (テストではパイプを stdin に設定している) というわけで、ここは isatty は気にしないように変えてみました。 ---------------------------------------- Bug #8644: valgrind error in a readline test https://bugs.ruby-lang.org/issues/8644#change-40576 Author: akr (Akira Tanaka) Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 2.1.0dev (2013-07-16 trunk 42006) [x86_64-linux] Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN test-all が readline のところで SEGV することがあったので、 とりあえず valgrind をかけてみたところ、ひとつ問題を指摘されました。 % ./ruby -v ruby 2.1.0dev (2013-07-16 trunk 42006) [x86_64-linux] % valgrind ./ruby -I.ext/x86_64-linux ../../ruby/test/runner.rb ../../ruby/test/readline -n test_closed_outstream ==27651== Memcheck, a memory error detector ==27651== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==27651== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==27651== Command: ./ruby -I.ext/x86_64-linux ../../ruby/test/runner.rb ../../ruby/test/readline -n test_closed_outstream ==27651== Run options: -n test_closed_outstream # Running tests: [1/1] TestReadline#test_closed_outstream==27651== Invalid read of size 4 ==27651== at 0x597B610: fileno (fileno.c:37) ==27651== by 0x74A3EA6: readline_readline (readline.c:397) ==27651== by 0x390B39: call_cfunc_m1 (vm_insnhelper.c:1348) ==27651== by 0x396943: vm_call_cfunc_with_frame (vm_insnhelper.c:1492) ==27651== by 0x395144: vm_call_cfunc (vm_insnhelper.c:1582) ==27651== by 0x394915: vm_call_method (vm_insnhelper.c:1774) ==27651== by 0x396A84: vm_call_general (vm_insnhelper.c:1925) ==27651== by 0x3724DC: vm_exec_core (insns.def:1017) ==27651== by 0x383DDF: vm_exec (vm.c:1198) ==27651== by 0x389DBD: invoke_block_from_c (vm.c:646) ==27651== by 0x38E299: vm_yield (vm.c:677) ==27651== by 0x380012: rb_yield_0 (vm_eval.c:937) ==27651== Address 0x847a1a0 is 0 bytes inside a block of size 568 free'd ==27651== at 0x4C27D4E: free (vg_replace_malloc.c:427) ==27651== by 0x5977CCC: fclose@@GLIBC_2.2.5 (iofclose.c:88) ==27651== by 0x190F5C: nogvl_fclose (io.c:4048) ==27651== by 0x3A33FC: call_without_gvl (thread.c:1244) ==27651== by 0x3A3532: rb_thread_call_without_gvl (thread.c:1354) ==27651== by 0x190E7C: maygvl_fclose (io.c:4057) ==27651== by 0x190620: fptr_finalize (io.c:4099) ==27651== by 0x16C922: rb_io_fptr_cleanup (io.c:4130) ==27651== by 0x16CAE7: rb_io_close (io.c:4221) ==27651== by 0x17A2F1: rb_io_close_m (io.c:4250) ==27651== by 0x390B62: call_cfunc_0 (vm_insnhelper.c:1354) ==27651== by 0x396943: vm_call_cfunc_with_frame (vm_insnhelper.c:1492) ==27651== Finished tests in 0.521803s, 1.9164 tests/s, 5.7493 assertions/s. 1 tests, 3 assertions, 0 failures, 0 errors, 0 skips ruby -v: ruby 2.1.0dev (2013-07-16 trunk 42006) [x86_64-linux] ==27651== ==27651== HEAP SUMMARY: ==27651== in use at exit: 1,905,554 bytes in 30,452 blocks ==27651== total heap usage: 94,021 allocs, 63,569 frees, 19,535,963 bytes allocated ==27651== ==27651== LEAK SUMMARY: ==27651== definitely lost: 447,671 bytes in 3,643 blocks ==27651== indirectly lost: 979,312 bytes in 17,524 blocks ==27651== possibly lost: 0 bytes in 0 blocks ==27651== still reachable: 478,571 bytes in 9,285 blocks ==27651== suppressed: 0 bytes in 0 blocks ==27651== Rerun with --leak-check=full to see details of leaked memory ==27651== ==27651== For counts of detected and suppressed errors, rerun with: -v ==27651== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) ちょっとソースを見たところ、fclose した後に fileno しているようですが、 これはよろしくないんじゃないでしょうか。 valgrind で指摘されたのが原因かどうかはわかりませんが、 SEGV したときのログもつけておきます。 (長すぎるので消しました。test_closed_outstream-segv.txt をみてください。) -- http://bugs.ruby-lang.org/