Project

General

Profile

Bug #4683 » 0001-io.c-copy_stream-execute-interrupts-and-retry.patch

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

View differences:

io.c
#include "ruby/ruby.h"
#include "ruby/io.h"
#include "vm_core.h"
#include "dln.h"
#include <ctype.h>
#include <errno.h>
......
VALUE th;
};
static void *
exec_interrupts(void *arg)
{
rb_thread_t *th = arg;
rb_threadptr_execute_interrupts(th);
return NULL;
}
/*
* returns TRUE if the preceding system call was interrupted
* so we can continue. If the thread was interrupted, we
* reacquire the GVL to execute interrupts before continuing.
*/
static int
nogvl_copy_stream_continue_p(struct copy_stream_struct *stp)
{
switch (errno) {
case EINTR:
#if defined(ERESTART)
case ERESTART:
#endif
if (rb_thread_interrupted(stp->th))
rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
return TRUE;
}
return FALSE;
}
static int
maygvl_copy_stream_wait_read(struct copy_stream_struct *stp)
{
int ret;
rb_fd_zero(&stp->fds);
rb_fd_set(stp->src_fd, &stp->fds);
ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
do {
rb_fd_zero(&stp->fds);
rb_fd_set(stp->src_fd, &stp->fds);
ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
} while (ret == -1 && nogvl_copy_stream_continue_p(stp));
if (ret == -1) {
stp->syserr = "select";
stp->error_no = errno;
......
nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
{
int ret;
rb_fd_zero(&stp->fds);
rb_fd_set(stp->dst_fd, &stp->fds);
ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
do {
rb_fd_zero(&stp->fds);
rb_fd_set(stp->dst_fd, &stp->fds);
ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
} while (ret == -1 && nogvl_copy_stream_continue_p(stp));
if (ret == -1) {
stp->syserr = "select";
stp->error_no = errno;
......
}
}
if (ss == -1) {
if (nogvl_copy_stream_continue_p(stp))
goto retry_sendfile;
switch (errno) {
case EINVAL:
#ifdef ENOSYS
......
#endif
if (maygvl_copy_stream_wait_readwrite(stp) == -1)
return -1;
if (rb_thread_interrupted(stp->th))
return -1;
goto retry_sendfile;
}
stp->syserr = "sendfile";
......
return 0;
}
if (ss == -1) {
if (nogvl_copy_stream_continue_p(stp))
goto retry_read;
switch (errno) {
case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
......
while (len) {
ss = write(stp->dst_fd, buf+off, len);
if (ss == -1) {
if (nogvl_copy_stream_continue_p(stp))
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (nogvl_copy_stream_wait_write(stp) == -1)
return -1;
......
if (!use_eof)
copy_length -= ss;
if (rb_thread_interrupted(stp->th))
return;
}
}
(1-1/4)