Bug #8749 » readline-release-gvl-2.patch
| 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(); | ||
|     return NULL; | ||
| } | ||
| 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 | ||
- « Previous
- 1
- 2
- Next »