Bug #923

`initialize_copy': wrong argument type #<Class:0x825d23c> (expected Data) (TypeError)

Added by Yukihiro Matsumoto about 3 years ago. Updated 10 months ago.

[ruby-dev:37573]
Status:Closed Start date:
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:core
Target version:1.9.1 Release Candidate
ruby -v:

Description

まつもと ゆきひろです

In message "Re: [ruby-dev:37572] [Bug:1.9] `initialize_copy': wrong argument type #<Class:0x825d23c> (expected Data) (TypeError)"
    on Wed, 24 Dec 2008 01:44:13 +0900, Tanaka Akira <akr@fsij.org> writes:
|
|以下のプログラムで、
|  wrong argument type #<Class:0x825d23c> (expected Data) (TypeError)
|という奇妙なエラーが出ます。
|
|% ./ruby -ve 'f = open("/tmp/x", "w")
|1000.times { f.dup.print "a" }
|GC.start
|'

IOのファイナライザを実行する時点ではwrite_lockがすでに解放さ
れちゃってるからのようです。とりあえず、

  * ファイナライザ実行前にwrite_lockをクリア
  * io_fflushでwrite_lockを問答無用で参照していたのをやめる

という対応で上記のプログラムは動いているように見えます。が、
わざわざwrite_lockをかけていたのをはずしちゃって良いのかとい
う判断は私にはつきかねます。

パッチを添付します。

--- a/io.c
+++ b/io.c
@@ -558,7 +558,13 @@ io_fflush(rb_io_t *fptr)
   retry:
     if (fptr->wbuf_len == 0)
         return 0;
-    r = rb_mutex_synchronize(fptr->write_lock, io_flush_buffer, (VALUE)fptr);
+    if (fptr->write_lock) {
+	r = rb_mutex_synchronize(fptr->write_lock, io_flush_buffer, (VALUE)fptr);
+    }
+    else {
+	long l = io_writable_length(fptr, fptr->wbuf_len);
+	r = rb_write_internal(fptr->fd, fptr->wbuf+fptr->wbuf_off, l);
+    }
     /* xxx: Other threads may modify wbuf.
      * A lock is required, definitely. */
     rb_io_check_closed(fptr);
@@ -3194,6 +3200,7 @@ rb_io_fptr_finalize(rb_io_t *fptr)
 {
     if (!fptr) return 0;
     fptr->pathv = Qnil;
+    fptr->write_lock = 0;
     if (0 <= fptr->fd)
 	rb_io_fptr_cleanup(fptr, Qtrue);
     if (fptr->rbuf) {

History

Updated by Nobuyoshi Nakada about 3 years ago

なかだです。

At Wed, 24 Dec 2008 10:08:22 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:37573]:
> IOのファイナライザを実行する時点ではwrite_lockがすでに解放さ
> れちゃってるからのようです。とりあえず、
> 
>   * ファイナライザ実行前にwrite_lockをクリア
>   * io_fflushでwrite_lockを問答無用で参照していたのをやめる
> 
> という対応で上記のプログラムは動いているように見えます。が、
> わざわざwrite_lockをかけていたのをはずしちゃって良いのかとい
> う判断は私にはつきかねます。

ファイナライザ実行時は競合するスレッドはないはずと思われるので、
はずしちゃってよいんではないでしょうか。

-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

Updated by Yuki Sonoda about 3 years ago

  • Category set to core
  • Priority changed from Low to Normal
  • Target version set to 1.9.1 Release Candidate

Updated by Yukihiro Matsumoto about 3 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:37574] Re: [Bug:1.9] `initialize_copy': wrong argument type #<Class:0x825d23c> (expected Data) (TypeError)"
    on Wed, 24 Dec 2008 11:31:05 +0900, Nobuyoshi Nakada <nobu@ruby-lang.org> writes:

|> わざわざwrite_lockをかけていたのをはずしちゃって良いのかとい
|> う判断は私にはつきかねます。
|
|ファイナライザ実行時は競合するスレッドはないはずと思われるので、
|はずしちゃってよいんではないでしょうか。

んじゃ、コミットします。ところで、GILがある以上、mutexを使わ
なくても単純なフラグでロックが実現できそうな気がするんですが。
そうするといろいろコストが安そうですが、そうでもないんですか
ね。

Updated by Nobuyoshi Nakada about 3 years ago

なかだです。

At Wed, 24 Dec 2008 20:30:21 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:37581]:
> |> わざわざwrite_lockをかけていたのをはずしちゃって良いのかとい
> |> う判断は私にはつきかねます。
> |
> |ファイナライザ実行時は競合するスレッドはないはずと思われるので、
> |はずしちゃってよいんではないでしょうか。
> 
> んじゃ、コミットします。ところで、GILがある以上、mutexを使わ
> なくても単純なフラグでロックが実現できそうな気がするんですが。
> そうするといろいろコストが安そうですが、そうでもないんですか
> ね。

書き込みがblocking regionで並行動作するので、通常のflushでは
mutexが必要です。ファイナライザが走る時点では、そういうスレッド
は終了しているはず(だから解放できる)だと思います。

-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

Updated by Yukihiro Matsumoto about 3 years ago

まつもと ゆきひろです

In message "Re: [ruby-dev:37589] Re: [Bug:1.9] `initialize_copy': wrong argument type #<Class:0x825d23c> (expected Data) (TypeError)"
    on Thu, 25 Dec 2008 04:46:23 +0900, Nobuyoshi Nakada <nobu@ruby-lang.org> writes:

|書き込みがblocking regionで並行動作するので、通常のflushでは
|mutexが必要です。ファイナライザが走る時点では、そういうスレッド
|は終了しているはず(だから解放できる)だと思います。

そういえばそういう話でしたね。すっかり忘れてました。

Updated by Yuki Sonoda about 3 years ago

  • Status changed from Open to Closed
applied in r21039

Also available in: Atom PDF