[#47562] [Backport 200 - Backport #8716][Open] segmation fault 正規表現で大量のグループを利用時 — "taka-yoshi (taka-yoshi taka)" <smokeonthewater222@...>

15 messages 2013/08/01

[#47569] [ruby-trunk - Feature #8726][Open] Class#source_location — "takiuchi (Genki Takiuchi)" <genki@...21g.com>

14 messages 2013/08/03

[ruby-dev:47041] Re: [ruby-trunk - Bug #8749][Open] Readline.readline stops STDOUT?

From: Tanaka Akira <akr@...>
Date: 2013-08-08 13:37:10 UTC
List: ruby-dev #47041
2013/8/8 Tanaka Akira <akr@fsij.org>:
> 2013年8月8日 8:05 Tanaka Akira <akr@fsij.org>:
>
>> でも、readline_getc では単に GVL を外して rl_getc を呼べばいいのではないか、という気もします。
>
> こうするなら、こうですかねぇ。

おっと、これだと ^C が効きませんでした。
こうかな。

% svn diff --diff-cmd diff -x '-u -p'
Index: ext/readline/readline.c
===================================================================
--- ext/readline/readline.c	(revision 42432)
+++ 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,15 +136,19 @@ 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);
+    int fd = fileno(input);
+    char ch;
+    ssize_t ss;
+    int ret;
+
 #if defined(_WIN32)
     {
         INPUT_RECORD ir;
@@ -151,19 +156,19 @@ readline_getc(FILE *input)
         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 +177,56 @@ 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;
-    }
+
+  again:
+    ss = read(fd, &ch, 1);
+    if (ss == 0)
+        return EOF;
+    if (ss == -1) {
+        if (errno == EINTR)
+            return EOF;
+        if (errno == EWOULDBLOCK || errno == EAGAIN) {
+#ifdef HAVE_POLL
+            struct pollfd pfd;
+            pfd.fd = fd;
+            pfd.events = POLLIN;
+            pfd.revents = 0;
+            ret = poll(&pfd, 1, -1);
+            if (ret < 0)
+                return EOF;
+#else
+            rb_fdset_t rfds;
+            rb_fd_init(&rfds);
+            rb_fd_set(fd, &rfds);
+            ret = rb_fd_select(fd+1, &rfds, NULL, NULL, NULL);
+            rb_fd_term(&rfds);
+            if (ret < 0)
+                return EOF;
 #endif
-    return FIX2INT(c);
+            goto again;
+        }
+    }
+    return (unsigned char)ch;
+}
+
+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]

In This Thread