0001-io.c-copy_stream-execute-interrupts-and-retry.patch

patch to fix the issue - Eric Wong, 05/13/2011 06:56 AM

Download (4.02 KB)

View differences:

io.c
13 13

  
14 14
#include "ruby/ruby.h"
15 15
#include "ruby/io.h"
16
#include "vm_core.h"
16 17
#include "dln.h"
17 18
#include <ctype.h>
18 19
#include <errno.h>
......
8377 8378
    VALUE th;
8378 8379
};
8379 8380

  
8381
static void *
8382
exec_interrupts(void *arg)
8383
{
8384
    rb_thread_t *th = arg;
8385
    rb_threadptr_execute_interrupts(th);
8386
    return NULL;
8387
}
8388

  
8389
/*
8390
 * returns TRUE if the preceding system call was interrupted
8391
 * so we can continue.  If the thread was interrupted, we
8392
 * reacquire the GVL to execute interrupts before continuing.
8393
 */
8394
static int
8395
nogvl_copy_stream_continue_p(struct copy_stream_struct *stp)
8396
{
8397
    switch (errno) {
8398
      case EINTR:
8399
#if defined(ERESTART)
8400
      case ERESTART:
8401
#endif
8402
	if (rb_thread_interrupted(stp->th))
8403
	    rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
8404
	return TRUE;
8405
    }
8406
    return FALSE;
8407
}
8408

  
8380 8409
static int
8381 8410
maygvl_copy_stream_wait_read(struct copy_stream_struct *stp)
8382 8411
{
8383 8412
    int ret;
8384
    rb_fd_zero(&stp->fds);
8385
    rb_fd_set(stp->src_fd, &stp->fds);
8386
    ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
8413

  
8414
    do {
8415
	rb_fd_zero(&stp->fds);
8416
	rb_fd_set(stp->src_fd, &stp->fds);
8417
	ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
8418
    } while (ret == -1 && nogvl_copy_stream_continue_p(stp));
8419

  
8387 8420
    if (ret == -1) {
8388 8421
        stp->syserr = "select";
8389 8422
        stp->error_no = errno;
......
8396 8429
nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
8397 8430
{
8398 8431
    int ret;
8399
    rb_fd_zero(&stp->fds);
8400
    rb_fd_set(stp->dst_fd, &stp->fds);
8401
    ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
8432

  
8433
    do {
8434
	rb_fd_zero(&stp->fds);
8435
	rb_fd_set(stp->dst_fd, &stp->fds);
8436
	ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
8437
    } while (ret == -1 && nogvl_copy_stream_continue_p(stp));
8438

  
8402 8439
    if (ret == -1) {
8403 8440
        stp->syserr = "select";
8404 8441
        stp->error_no = errno;
......
8545 8582
        }
8546 8583
    }
8547 8584
    if (ss == -1) {
8585
	if (nogvl_copy_stream_continue_p(stp))
8586
	    goto retry_sendfile;
8548 8587
        switch (errno) {
8549 8588
	  case EINVAL:
8550 8589
#ifdef ENOSYS
......
8557 8596
#endif
8558 8597
            if (maygvl_copy_stream_wait_readwrite(stp) == -1)
8559 8598
                return -1;
8560
            if (rb_thread_interrupted(stp->th))
8561
                return -1;
8562 8599
            goto retry_sendfile;
8563 8600
        }
8564 8601
        stp->syserr = "sendfile";
......
8588 8625
        return 0;
8589 8626
    }
8590 8627
    if (ss == -1) {
8628
	if (nogvl_copy_stream_continue_p(stp))
8629
	    goto retry_read;
8591 8630
        switch (errno) {
8592 8631
	  case EAGAIN:
8593 8632
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
......
8617 8656
    while (len) {
8618 8657
        ss = write(stp->dst_fd, buf+off, len);
8619 8658
        if (ss == -1) {
8659
	    if (nogvl_copy_stream_continue_p(stp))
8660
		continue;
8620 8661
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
8621 8662
                if (nogvl_copy_stream_wait_write(stp) == -1)
8622 8663
                    return -1;
......
8687 8728

  
8688 8729
        if (!use_eof)
8689 8730
            copy_length -= ss;
8690

  
8691
        if (rb_thread_interrupted(stp->th))
8692
            return;
8693 8731
    }
8694 8732
}
8695 8733