Project

General

Profile

Bug #8749 » readline-release-gvl.patch

akr (Akira Tanaka), 08/12/2013 09:21 PM

View differences:

ext/readline/readline.c (working copy)
#include "ruby/ruby.h"
#include "ruby/io.h"
#include "ruby/thread.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
......
#define rl_getc(f) EOF
#endif
static int readline_getc(FILE *);
struct getc_struct {
FILE *input;
int ret;
};
static void *
check_ints(void *data)
{
rb_thread_check_ints();
}
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);
int fd = fileno(input);
char ch;
ssize_t ss;
int ret;
#if defined(_WIN32)
{
INPUT_RECORD ir;
......
static int prior_key = '0';
for (;;) {
if (prior_key > 0xff) {
prior_key = rl_getc(rl_instream);
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(rl_instream);
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 {
......
}
}
#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) {
interrupt:
rb_thread_call_with_gvl(check_ints, NULL);
goto again;
}
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) {
if (errno == EINTR)
goto interrupt;
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) {
if (errno == EINTR)
goto interrupt;
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 *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
(1-1/2)