readline-release-gvl-5.patch

Akira Tanaka, 10/23/2013 06:17 PM

Download (7.99 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 run;
144
  int ret;
145
  int err;
146
};
147

  
139 148
static int
140
readline_getc(FILE *input)
149
getc_body(FILE *input)
141 150
{
142
    rb_io_t *ifp = 0;
143
    VALUE c;
144
    if (!readline_instream) return rl_getc(input);
145
    GetOpenFile(readline_instream, ifp);
151
    int fd = fileno(input);
152
    char ch;
153
    ssize_t ss;
154

  
146 155
#if defined(_WIN32)
147 156
    {
148 157
        INPUT_RECORD ir;
......
150 159
        static int prior_key = '0';
151 160
        for (;;) {
152 161
            if (prior_key > 0xff) {
153
                prior_key = rl_getc(rl_instream);
162
                prior_key = rl_getc(input);
154 163
                return prior_key;
155 164
            }
156
            if (PeekConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n)) {
165
            if (PeekConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n)) {
157 166
                if (n == 1) {
158 167
                    if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
159
                        prior_key = rl_getc(rl_instream);
168
                        prior_key = rl_getc(input);
160 169
                        return prior_key;
161 170
                    } else {
162
                        ReadConsoleInput((HANDLE)_get_osfhandle(ifp->fd), &ir, 1, &n);
171
                        ReadConsoleInput((HANDLE)_get_osfhandle(fd), &ir, 1, &n);
163 172
                    }
164 173
                } else {
165
                    HANDLE h = (HANDLE)_get_osfhandle(ifp->fd);
174
                    HANDLE h = (HANDLE)_get_osfhandle(fd);
166 175
                    rb_w32_wait_events(&h, 1, INFINITE);
167 176
                }
168 177
            } else {
......
171 180
        }
172 181
    }
173 182
#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;
183

  
184
    ss = read(fd, &ch, 1);
185
    if (ss == 0) {
186
        errno = 0;
187
        return EOF;
188
    }
189
    if (ss != 1)
190
        return EOF;
191
    return (unsigned char)ch;
192
}
193

  
194
static void *
195
getc_func(void *data1)
196
{
197
    struct getc_struct *p = data1;
198
    FILE *input = p->input;
199
    p->run = 1;
200
    errno = 0;
201
    p->ret = getc_body(input);
202
    p->err = errno;
203
    return NULL;
204
}
205

  
206
static int
207
readline_getc(FILE *input)
208
{
209
    struct getc_struct data;
210
    data.input = input;
211
  again:
212
    data.run = 0;
213
    data.ret = EOF;
214
    data.err = 0;
215
    rb_thread_call_without_gvl2(getc_func, &data, RUBY_UBF_IO, NULL);
216
    if (!data.run) {
217
        rb_thread_check_ints();
218
        goto again;
219
    }
220
    if (data.ret == EOF) {
221
        if (data.err == 0) {
222
            return EOF;
223
        }
224
        if (data.err == EINTR) {
225
            rb_thread_check_ints();
226
            goto again;
227
        }
228
        if (data.err == EWOULDBLOCK || data.err == EAGAIN) {
229
            int ret;
230
            int fd = fileno(input);
231
            if (fd < 0)
232
                rb_bug("readline_getc: input closed unexpectedly or memory corrupted");
233
            ret = rb_wait_for_single_fd(fd, RB_WAITFD_IN, NULL);
234
            if (ret != -1 || errno == EINTR)
235
                goto again;
236
            rb_sys_fail("rb_wait_for_single_fd");
237
        }
238
        errno = data.err;
239
        rb_sys_fail("read");
186 240
    }
187
#endif
188
    return FIX2INT(c);
241
    return data.ret;
189 242
}
243

  
190 244
#elif defined HAVE_RL_EVENT_HOOK
191 245
#define BUSY_WAIT 0
192 246

  
......
287 341
    return (VALUE)readline((char *)prompt);
288 342
}
289 343

  
344
static void
345
clear_rl_instream(void)
346
{
347
    if (readline_rl_instream) {
348
        fclose(readline_rl_instream);
349
        if (rl_instream == readline_rl_instream)
350
            rl_instream = NULL;
351
        readline_rl_instream = NULL;
352
    }
353
    readline_instream = Qfalse;
354
}
355

  
356
static void
357
clear_rl_outstream(void)
358
{
359
    if (readline_rl_outstream) {
360
        fclose(readline_rl_outstream);
361
        if (rl_outstream == readline_rl_outstream)
362
            rl_outstream = NULL;
363
        readline_rl_outstream = NULL;
364
    }
365
    readline_outstream = Qfalse;
366
}
367

  
290 368
/*
291 369
 * call-seq:
292 370
 *   Readline.readline(prompt = "", add_hist = false) -> string or nil
......
390 468

  
391 469
    if (readline_instream) {
392 470
        rb_io_t *ifp;
393
        GetOpenFile(readline_instream, ifp);
471
        rb_io_check_initialized(ifp = RFILE(rb_io_taint_check(readline_instream))->fptr);
394 472
        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");
473
            clear_rl_instream();
474
            rb_raise(rb_eIOError, "closed readline input");
401 475
        }
402 476
    }
403 477

  
404 478
    if (readline_outstream) {
405 479
        rb_io_t *ofp;
406
        GetOpenFile(readline_outstream, ofp);
480
        rb_io_check_initialized(ofp = RFILE(rb_io_taint_check(readline_outstream))->fptr);
407 481
        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");
482
            clear_rl_outstream();
483
            rb_raise(rb_eIOError, "closed readline output");
414 484
        }
415 485
    }
416 486

  
......
453 523
    return result;
454 524
}
455 525

  
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 526
/*
474 527
 * call-seq:
475 528
 *   Readline.input = input
......
501 554
            errno = save_errno;
502 555
            rb_sys_fail("fdopen");
503 556
        }
504
        rl_instream = f;
557
        rl_instream = readline_rl_instream = f;
505 558
        readline_instream = input;
506 559
    }
507 560
    return input;
508 561
}
509 562

  
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 563
/*
528 564
 * call-seq:
529 565
 *   Readline.output = output
......
555 591
            errno = save_errno;
556 592
            rb_sys_fail("fdopen");
557 593
        }
558
        rl_outstream = f;
594
        rl_outstream = readline_rl_outstream = f;
559 595
        readline_outstream = output;
560 596
    }
561 597
    return output;
......
1955 1991

  
1956 1992
    rb_gc_register_address(&readline_instream);
1957 1993
    rb_gc_register_address(&readline_outstream);
1958

  
1959
    readline_s_set_input(mReadline, rb_stdin);
1960 1994
}