readline-release-gvl-3.patch

Akira Tanaka, 10/21/2013 11:51 PM

Download (8.06 KB)

View differences:

ext/readline/readline.c (working copy)
35 35

  
36 36
#include "ruby/ruby.h"
37 37
#include "ruby/io.h"
38
#include "ruby/thread.h"
38 39

  
39 40
#ifdef HAVE_UNISTD_H
40 41
#include <unistd.h>
......
128 129

  
129 130
static VALUE readline_instream;
130 131
static VALUE readline_outstream;
132
static FILE *readline_rl_instream;
133
static FILE *readline_rl_outstream;
131 134

  
132 135
#if defined HAVE_RL_GETC_FUNCTION
133 136

  
......
135 138
#define rl_getc(f) EOF
136 139
#endif
137 140

  
138
static int readline_getc(FILE *);
141
struct getc_struct {
142
  FILE *input;
143
  int ret;
144
};
145

  
146
static void *
147
check_ints(void *data)
148
{
149
    rb_thread_check_ints();
150
    return NULL;
151
}
152

  
139 153
static int
140
readline_getc(FILE *input)
154
getc_body(FILE *input)
141 155
{
142
    rb_io_t *ifp = 0;
143
    VALUE c;
144
    if (!readline_instream) return rl_getc(input);
145
    GetOpenFile(readline_instream, ifp);
156
    int fd = fileno(input);
157
    char ch;
158
    ssize_t ss;
159
    int ret;
160

  
146 161
#if defined(_WIN32)
147 162
    {
148 163
        INPUT_RECORD ir;
......
150 165
        static int prior_key = '0';
151 166
        for (;;) {
152 167
            if (prior_key > 0xff) {
153
                prior_key = rl_getc(rl_instream);
168
                prior_key = rl_getc(input);
154 169
                return prior_key;
155 170
            }
156
            if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) {
171
            if (PeekConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n)) {
157 172
                if (n == 1) {
158 173
                    if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
159
                        prior_key = rl_getc(rl_instream);
174
                        prior_key = rl_getc(input);
160 175
                        return prior_key;
161 176
                    } else {
162
                        ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n);
177
                        ReadConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n);
163 178
                    }
164 179
                } else {
165
                    HANDLE h = (HANDLE)_get_osfhandle(ifp->fd);
180
                    HANDLE h = (HANDLE)_get_osfhandle(fd);
166 181
                    rb_w32_wait_events(&h, 1, INFINITE);
167 182
                }
168 183
            } else {
......
171 186
        }
172 187
    }
173 188
#endif
174
    c = rb_io_getbyte(readline_instream);
175
    if (NIL_P(c)) return EOF;
176
#ifdef ESC
177
    if (c == INT2FIX(ESC) &&
178
        RL_ISSTATE(RL_STATE_ISEARCH) && /* isn't needed in other states? */
179
        rb_io_read_pending(ifp)) {
180
        int meta = 0;
181
        c = rb_io_getbyte(readline_instream);
182
        if (FIXNUM_P(c) && isascii(FIX2INT(c))) meta = 1;
183
        rb_io_ungetbyte(readline_instream, c);
184
        if (meta) rl_execute_next(ESC);
185
        return ESC;
186
    }
189

  
190
  again:
191
    ss = read(fd, &ch, 1);
192
    if (ss == 0)
193
        return EOF;
194
    if (ss == -1) {
195
        if (errno == EINTR) {
196
          interrupt:
197
            rb_thread_call_with_gvl(check_ints, NULL);
198
            goto again;
199
        }
200
        if (errno == EWOULDBLOCK || errno == EAGAIN) {
201
#ifdef HAVE_POLL
202
            struct pollfd pfd;
203
            pfd.fd = fd;
204
            pfd.events = POLLIN;
205
            pfd.revents = 0;
206
            ret = poll(&pfd, 1, -1);
207
            if (ret < 0) {
208
                if (errno == EINTR)
209
                    goto interrupt;
210
                return EOF;
211
            }
212
#else
213
            rb_fdset_t rfds;
214
            rb_fd_init(&rfds);
215
            rb_fd_set(fd, &rfds);
216
            ret = rb_fd_select(fd+1, &rfds, NULL, NULL, NULL);
217
            rb_fd_term(&rfds);
218
            if (ret < 0) {
219
                if (errno == EINTR)
220
                    goto interrupt;
221
                return EOF;
222
            }
187 223
#endif
188
    return FIX2INT(c);
224
            goto again;
225
        }
226
    }
227
    return (unsigned char)ch;
189 228
}
229

  
230
static void *
231
getc_func(void *data1)
232
{
233
    struct getc_struct *p = data1;
234
    FILE *input = p->input;
235
    p->ret = getc_body(input);
236
    return NULL;
237
}
238

  
239
static int
240
readline_getc(FILE *input)
241
{
242
    struct getc_struct data;
243
    data.input = input;
244
    data.ret = -1;
245
    rb_thread_call_without_gvl(getc_func, &data, RUBY_UBF_IO, NULL);
246
    return data.ret;
247
}
248

  
190 249
#elif defined HAVE_RL_EVENT_HOOK
191 250
#define BUSY_WAIT 0
192 251

  
......
287 346
    return (VALUE)readline((char *)prompt);
288 347
}
289 348

  
349
static void
350
clear_rl_instream(void)
351
{
352
    if (readline_rl_instream) {
353
        fclose(readline_rl_instream);
354
        if (rl_instream == readline_rl_instream)
355
            rl_instream = NULL;
356
        readline_rl_instream = NULL;
357
    }
358
    readline_instream = Qfalse;
359
}
360

  
361
static void
362
clear_rl_outstream(void)
363
{
364
    if (readline_rl_outstream) {
365
        fclose(readline_rl_outstream);
366
        if (rl_outstream == readline_rl_outstream)
367
            rl_outstream = NULL;
368
        readline_rl_outstream = NULL;
369
    }
370
    readline_outstream = Qfalse;
371
}
372

  
290 373
/*
291 374
 * call-seq:
292 375
 *   Readline.readline(prompt = "", add_hist = false) -> string or nil
......
390 473

  
391 474
    if (readline_instream) {
392 475
        rb_io_t *ifp;
393
        GetOpenFile(readline_instream, ifp);
476
        rb_io_check_initialized(ifp = RFILE(rb_io_taint_check(readline_instream))->fptr);
394 477
        if (ifp->fd < 0) {
395
            if (rl_instream) {
396
                fclose(rl_instream);
397
                rl_instream = NULL;
398
            }
399
            readline_instream = Qfalse;
400
            rb_raise(rb_eIOError, "closed stdin");
478
            clear_rl_instream();
479
            rb_raise(rb_eIOError, "closed readline input");
401 480
        }
402 481
    }
403 482

  
404 483
    if (readline_outstream) {
405 484
        rb_io_t *ofp;
406
        GetOpenFile(readline_outstream, ofp);
485
        rb_io_check_initialized(ofp = RFILE(rb_io_taint_check(readline_outstream))->fptr);
407 486
        if (ofp->fd < 0) {
408
            if (rl_outstream) {
409
                fclose(rl_outstream);
410
                rl_outstream = NULL;
411
            }
412
            readline_outstream = Qfalse;
413
            rb_raise(rb_eIOError, "closed stdout");
487
            clear_rl_outstream();
488
            rb_raise(rb_eIOError, "closed readline output");
414 489
        }
415 490
    }
416 491

  
......
453 528
    return result;
454 529
}
455 530

  
456
static void
457
clear_rl_instream(void)
458
{
459
    rb_io_t *ifp;
460
    if (rl_instream) {
461
        if (readline_instream) {
462
            rb_io_check_initialized(ifp = RFILE(rb_io_taint_check(readline_instream))->fptr);
463
            if (ifp->fd < 0 || fileno(rl_instream) == ifp->fd) {
464
                fclose(rl_instream);
465
                rl_instream = NULL;
466
            }
467
        }
468
        readline_instream = Qfalse;
469
        rl_instream = NULL;
470
    }
471
}
472

  
473 531
/*
474 532
 * call-seq:
475 533
 *   Readline.input = input
......
501 559
            errno = save_errno;
502 560
            rb_sys_fail("fdopen");
503 561
        }
504
        rl_instream = f;
562
        rl_instream = readline_rl_instream = f;
505 563
        readline_instream = input;
506 564
    }
507 565
    return input;
508 566
}
509 567

  
510
static void
511
clear_rl_outstream(void)
512
{
513
    rb_io_t *ofp;
514
    if (rl_outstream) {
515
        if (readline_outstream) {
516
            rb_io_check_initialized(ofp = RFILE(rb_io_taint_check(readline_outstream))->fptr);
517
            if (ofp->fd < 0 || fileno(rl_outstream) == ofp->fd) {
518
                fclose(rl_outstream);
519
                rl_outstream = NULL;
520
            }
521
        }
522
        readline_outstream = Qfalse;
523
        rl_outstream = NULL;
524
    }
525
}
526

  
527 568
/*
528 569
 * call-seq:
529 570
 *   Readline.output = output
......
555 596
            errno = save_errno;
556 597
            rb_sys_fail("fdopen");
557 598
        }
558
        rl_outstream = f;
599
        rl_outstream = readline_rl_outstream = f;
559 600
        readline_outstream = output;
560 601
    }
561 602
    return output;
......
1955 1996

  
1956 1997
    rb_gc_register_address(&readline_instream);
1957 1998
    rb_gc_register_address(&readline_outstream);
1958

  
1959
    readline_s_set_input(mReadline, rb_stdin);
1960 1999
}