[#7064] How to put version number of shared library? — Ryo HAYASAKA <hayasaka@...21.u-aizu.ac.jp>
早坂@会津大学です。
4 messages
1999/06/02
[#7082] [BUG] unpack('m') — 民斗 <tommy@...>
民斗です。
6 messages
1999/06/07
[#7091] [BUG?] load in thread — keiju@... (Keiju ISHITSUKA)
けいじゅ@日本ラショナルソフトウェアです.
7 messages
1999/06/09
[#7092] Re: [BUG?] load in thread
— matz@... (Yukihiro Matsumoto)
1999/06/09
まつもと ゆきひろです
[#7102] Ruby 1.3.4-990611 — Yukihiro Matsumoto <matz@...>
Ruby 1.3.4-990611 is out, check out:
20 messages
1999/06/11
[#7108] Re: Ruby 1.3.4-990611
— Koji Arai <JCA02266@...>
1999/06/12
新井です。
[#7123] Re: Ruby 1.3.4-990611
— nagai@...
1999/06/16
永井@知能.九工大です.
[#7110] --enable-shared support — Katsuyuki Komatsu <komatsu@...>
小松です。
11 messages
1999/06/14
[#7111] Re: --enable-shared support
— WATANABE Tetsuya <tetsu@...>
1999/06/15
渡辺哲也です。
[#7173] [BUG] <<`HERE_DOC` — Koji Arai <JCA02266@...>
新井です。
7 messages
1999/06/22
[#7178] [PATCH] rubydb3x.el, ruby-mode.el — nobu.nakada@...
中田です。
7 messages
1999/06/22
[#7181] acknowledgement — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
6 messages
1999/06/23
[#7210] Ruby 1.3.4-990624 — Yukihiro Matsumoto <matz@...>
Ruby 1.3.4-990624 is out, check out:
7 messages
1999/06/24
[#7223] Ruby 1.3.4-990625 — Yukihiro Matsumoto <matz@...>
Ruby 1.3.4-990625 is out, check out:
14 messages
1999/06/25
[#7224] -Wl,-rpath on Linux (Re: Ruby 1.3.4-990625)
— Ryo HAYASAKA <hayasaka@...21.u-aizu.ac.jp>
1999/06/25
早坂@会津大学です。
[#7225] Re: -Wl,-rpath on Linux (Re: Ruby 1.3.4-990625)
— Katsuyuki Komatsu <komatsu@...>
1999/06/25
小松です。
[#7226] Re: -Wl,-rpath on Linux (Re: Ruby 1.3.4-990625)
— Katsuyuki Komatsu <komatsu@...>
1999/06/25
小松です。
[#7227] Re: -Wl,-rpath on Linux (Re: Ruby 1.3.4-990625)
— Katsuyuki Komatsu <komatsu@...>
1999/06/25
小松です。
[#7253] Re: Ruby 1.3.4-990625 — SHIROYAMA Takayuki <psi@...>
9 messages
1999/06/29
[#7258] TkVariable — Koji Arai <JCA02266@...>
新井です。
6 messages
1999/06/29
[ruby-dev:7159] Re: Ruby 1.3.4-990611
From:
matz@... (Yukihiro Matsumoto)
Date:
1999-06-22 01:15:40 UTC
List:
ruby-dev #7159
まつもと ゆきひろです
In message "[ruby-dev:7109] Re: Ruby 1.3.4-990611"
on 99/06/14, WATANABE Tetsuya <tetsu@jpn.hp.com> writes:
|動きが変わったのでお知らせします。
どうもです。
|$stdout = IO.popen('nkf -j', 'w')
|
|のように $stdout を上書きすると、出力時にプロセスがブロック
|してしまうことが起きました。
なかなか謎ですね。
|io.c 1495 に
|rb_obj_call_init((VALUE)port, 0, 0);
で解決してしまうところなんか(このメソッドは実質なにもしませ
ん)、ミステリです。正直言うとかなり悩みました。
しかし、これくらい詳細な情報を頂けると大体の謎は解けるもので
す。結論から言うと、「謎は全て解けたっ」です。
最初のヒントはこれです。
|GC との関係がありそうで、スクリプトから不要? な部分を削ると
|起きません。
GCは確かに怪しいですね。そして決めてはスタックトレースです。
これはいつも重要ですね。
|■ 止っているときの状況
|
|gdb 上で再現して、止っているところを backtrace しました。
|#3 0x8078b6f in rb_syswait ()
|#6 0x80642f9 in rb_io_fptr_finalize ()
|#8 0x8060494 in rb_gc_mark ()
|#9 0x8060a36 in rb_gc ()
なんか変なシンボル混じってますが、重要なのはこれらのシンボル
です。これはGCでIOが回収されて、その中でrb_syswait()が呼ばれ
ていることを表しています。
そこで調べてみると
$stdin = open("|..", "r")
のようなタイプではreopen()が使われています。つまり、元々の
$stdinにfdがdupされているわけです。
もうわかりましたね。つまり、open()によって生成されたpopenオ
ブジェクトはdupされた後、そのままゴミとなり、まだ終了もして
いないのにGCの中でwait4(2)されていたわけです。これではインタ
プリタ全体が停止してしまいます。
そこで、まずGC中ではwaitしないようにします。これでまず停止す
ると言う問題は解決します。
--- io.c~ Mon Jun 21 23:01:27 1999
+++ io.c Mon Jun 21 22:42:40 1999
@@ -884,8 +884,4 @@
fclose(fptr->f2);
}
- if (fptr->pid) {
- rb_syswait(fptr->pid);
- fptr->pid = 0;
- }
}
@@ -904,4 +900,8 @@
else {
fptr_finalize(fptr);
+ if (fptr->pid) {
+ rb_syswait(fptr->pid);
+ fptr->pid = 0;
+ }
}
fptr->f = fptr->f2 = NULL;
ただし、これで全ての問題が解決したかと言うとそうでもありませ
ん。以下の問題が気になります。
* dupしていないpopenオブジェクトがゴミになると、ゾンビが残っ
てしまう
* $std{in,out,err}への代入がreopenによって行われるのは直観
に反する。保存のために直前にdupを必要とするし
前者はまあ無視することにします。dupする時にカウンタを更新す
ることなど、やり方はないわけではないのですが、とりあえず気持
ちの問題に過ぎないので、これは将来への課題として残しておくこ
とにしましょう。
後者は昔から嫌だなと思っていたのでした。そこで、以下のような
ことをしてみることにしました。手元では動いているようですが、
どうでしょう。
これは内部的に実質reopenしているのですが、「$stdinの値を固定」
という以前のやや無理のある(他の代入モデルと違う)挙動を緩和し
てみました。これでdupは不要になります。
--- io.c~ Mon Jun 21 23:01:27 1999
+++ io.c Mon Jun 21 23:15:58 1999
@@ -2032,6 +2032,25 @@
}
+static int
+rb_dup(orig)
+ int orig;
+{
+ int fd;
+
+ fd = dup(orig);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = dup(orig);
+ }
+ if (fd < 0) {
+ rb_sys_fail(0);
+ }
+ }
+ return fd;
+}
+
static void
-rb_io_stdio_set(val, id, var)
+set_stdin(val, id, var)
VALUE val;
ID id;
@@ -2040,21 +2059,89 @@
OpenFile *fptr;
int fd;
+ char *mode;
+ if (val == *var) return;
if (TYPE(val) != T_FILE) {
rb_raise(rb_eTypeError, "%s must be IO object", rb_id2name(id));
}
- if (ruby_verbose) {
- rb_warn("assignment for %s is done by reopen", rb_id2name(id));
- }
- GetOpenFile(*var, fptr);
- fd = fileno(fptr->f);
+
GetOpenFile(val, fptr);
- if (fd == 0) {
rb_io_check_readable(fptr);
+
+ GetOpenFile(*var, fptr);
+ mode = rb_io_mode_string(fptr);
+ fd = rb_dup(fileno(fptr->f));
+ if (fileno(fptr->f) > 2) {
+ fclose(fptr->f);
}
- else {
+ fptr->f = rb_fdopen(fd, mode);
+
+ GetOpenFile(val, fptr);
+ dup2(fileno(fptr->f), 0);
+ fclose(fptr->f);
+ fptr->f = stdin;
+
+ *var = val;
+}
+
+static void
+set_outfile(val, id, var, stdf)
+ VALUE val;
+ ID id;
+ VALUE *var;
+ FILE *stdf;
+{
+ OpenFile *fptr;
+ FILE *f;
+ int fd;
+ char *mode;
+
+ if (val == *var) return;
+ rb_io_flush(*var);
+
+ if (TYPE(val) != T_FILE) {
+ rb_raise(rb_eTypeError, "%s must be IO object", rb_id2name(id));
+ }
+
+ GetOpenFile(val, fptr);
rb_io_check_writable(fptr);
+
+ GetOpenFile(*var, fptr);
+ mode = rb_io_mode_string(fptr);
+ f = GetWriteFile(fptr);
+ fd = rb_dup(fileno(f));
+ if (fileno(f) > 2) {
+ fclose(fptr->f);
+ }
+ f = rb_fdopen(fd, mode);
+ if (fptr->f2) fptr->f2 = f;
+ else fptr->f = f;
+
+ GetOpenFile(val, fptr);
+ f = GetWriteFile(fptr);
+ dup2(fileno(f), fileno(stdf));
+ fclose(f);
+ if (fptr->f2) fptr->f2 = stdf;
+ else fptr->f = stdf;
+
+ *var = val;
}
- rb_io_reopen(*var, val);
+
+static void
+set_stdout(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ set_outfile(val, id, var, stdout);
+}
+
+static void
+set_stderr(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ set_outfile(val, id, var, stderr);
}
@@ -2331,7 +2418,4 @@
#include <sys/select.h>
#endif
-#ifdef NT
-#define select(v, w, x, y, z) (-1) /* anytime fail */
-#endif
static VALUE
@@ -3100,9 +3184,9 @@
rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO);
- rb_define_hooked_variable("$stdin", &rb_stdin, 0, rb_io_stdio_set);
+ rb_define_hooked_variable("$stdin", &rb_stdin, 0, set_stdin);
rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO);
- rb_define_hooked_variable("$stdout", &rb_stdout, 0, rb_io_stdio_set);
+ rb_define_hooked_variable("$stdout", &rb_stdout, 0, set_stdout);
rb_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO);
- rb_define_hooked_variable("$stderr", &rb_stderr, 0, rb_io_stdio_set);
+ rb_define_hooked_variable("$stderr", &rb_stderr, 0, set_stderr);
rb_defout = rb_stdout;
rb_define_hooked_variable("$>", &rb_defout, 0, rb_io_defset);