From: Tanaka Akira <akr@...> Date: 2013-08-08T10:19:47+09:00 Subject: [ruby-dev:47037] Re: [ruby-trunk - Bug #8749][Open] Readline.readline stops STDOUT? 2013年8月8日 8:05 Tanaka Akira <akr@fsij.org>: > でも、readline_getc では単に GVL を外して rl_getc を呼べばいいのではないか、という気もします。 こうするなら、こうですかねぇ。 % 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 <unistd.h> @@ -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 arton さんが書いた Windows 用のコードが必要かどうかはよくわからないのですが、 いちおう残してあります。テストはしていません。 -- [田中 哲][たなか あきら][Tanaka Akira] _______________________________________________ ruby-dev mailing list ruby-dev@ruby-lang.org http://lists.ruby-lang.org/cgi-bin/mailman/listinfo/ruby-dev