From: Tanaka Akira Date: 2013-08-12T11:58:35+09:00 Subject: [ruby-dev:47611] Re: [ruby-cvs:49669] naruse:r42527 (trunk): refix r42525 set stdio_file only if stdio 2013年8月12日 11:38 NARUSE, Yui : > あぁ、[ruby-dev:47608]見てませんでした。 > >> そこでの f は fdopen で作ったものなので、stdin や stdout と等しくなることは >> ないと思うんですが、どうなんでしょうか。 >> そんなことはないのでしょうか。 > > ん?それは元のなんでもかんでも rb_io_stdio_file してたコードがバグってたって話ですか? rb_io_stdio_file で得られる FILE 構造体の寿命は readline 側からは制御できないので 問題だったのはそうでしょう。 それはそれとして、Ruby 1.9 以降は、blocking regeion で rl_getc を呼べばいいんじゃないの、 と思って http://bugs.ruby-lang.org/issues/8749 のメールにリプライしたのですが... なんか残ってないなぁ。 書いたパッチはこんなかんじで、こういう方向性はどうかなぁ。 editline での問題を解決するかどうかはわからないんですが。 % svn diff --diff-cmd diff -x '-u -p' Index: ext/readline/readline.c =================================================================== --- ext/readline/readline.c (revision 42429) +++ ext/readline/readline.c (working copy) @@ -35,6 +35,7 @@ #include "ruby/ruby.h" #include "ruby/io.h" +#include "ruby/thread.h" #ifdef HAVE_UNISTD_H #include @@ -135,35 +136,35 @@ static VALUE readline_outstream; #define rl_getc(f) EOF #endif -static int readline_getc(FILE *); +struct getc_struct { + FILE *input; + int ret; +}; + static int -readline_getc(FILE *input) +getc_body(FILE *input) { - rb_io_t *ifp = 0; - VALUE c; - if (!readline_instream) return rl_getc(input); - GetOpenFile(readline_instream, ifp); - if (rl_instream != ifp->stdio_file) return rl_getc(input); #if defined(_WIN32) + int fd = fileno(input); { INPUT_RECORD ir; int n; static int prior_key = '0'; for (;;) { if (prior_key > 0xff) { - prior_key = rl_getc(ifp->stdio_file); + prior_key = rl_getc(input); return prior_key; } - if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) { + if (PeekConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n)) { if (n == 1) { if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { - prior_key = rl_getc(ifp->stdio_file); + prior_key = rl_getc(input); return prior_key; } else { - ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n); + ReadConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n); } } else { - HANDLE h = (HANDLE)_get_osfhandle(ifp->fd); + HANDLE h = (HANDLE)_get_osfhandle(fd); rb_w32_wait_events(&h, 1, INFINITE); } } else { @@ -172,21 +173,27 @@ readline_getc(FILE *input) } } #endif - c = rb_io_getbyte(readline_instream); - if (NIL_P(c)) return EOF; -#ifdef ESC - if (c == INT2FIX(ESC) && - RL_ISSTATE(RL_STATE_ISEARCH) && /* isn't needed in other states? */ - rb_io_read_pending(ifp)) { - int meta = 0; - c = rb_io_getbyte(readline_instream); - if (FIXNUM_P(c) && isascii(FIX2INT(c))) meta = 1; - rb_io_ungetbyte(readline_instream, c); - if (meta) rl_execute_next(ESC); - return ESC; - } -#endif - return FIX2INT(c); + return rl_getc(input); +} + +static void * +getc_func(void *data1) +{ + struct getc_struct *p = data1; + FILE *input = p->input; + p->ret = getc_body(input); + return NULL; +} + +static int readline_getc(FILE *); +static int +readline_getc(FILE *input) +{ + struct getc_struct data; + data.input = input; + data.ret = -1; + rb_thread_call_without_gvl(getc_func, &data, RUBY_UBF_IO, NULL); + return data.ret; } #elif defined HAVE_RL_EVENT_HOOK #define BUSY_WAIT 0 -- [田中 哲][たなか あきら][Tanaka Akira]