Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 54 additions & 46 deletions ext/io/event/selector/epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,36 +590,29 @@ struct io_read_arguments {

int descriptor;

VALUE buffer;
// The remaining writable buffer region after applying the requested offset.
void *base;
size_t size;

// The minimum number of bytes requested by the caller.
size_t length;
size_t offset;
};

static
VALUE io_read_loop(VALUE _arguments) {
struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;

void *base;
size_t size;
rb_io_buffer_get_bytes_for_writing(arguments->buffer, &base, &size);

size_t length = arguments->length;
size_t offset = arguments->offset;
size_t total = 0;

// Ensure offset is within the bounds of the buffer to avoid size_t underflow and out-of-bounds pointer arithmetic on (char *)base + offset.
if (offset > size) {
return rb_fiber_scheduler_io_result(-1, EINVAL);
}

size_t maximum_size = size - offset;
size_t maximum_size = arguments->size;
while (maximum_size) {
ssize_t result = read(arguments->descriptor, (char*)base+offset, maximum_size);
ssize_t result = read(arguments->descriptor, (char*)arguments->base+total, maximum_size);

if (result > 0) {
total += result;
offset += result;
if ((size_t)result >= length) break;
maximum_size -= result;
length -= result;
} else if (result == 0) {
break;
Expand All @@ -628,8 +621,6 @@ VALUE io_read_loop(VALUE _arguments) {
} else {
return rb_fiber_scheduler_io_result(-1, errno);
}

maximum_size = size - offset;
}

return rb_fiber_scheduler_io_result(total, 0);
Expand All @@ -645,21 +636,34 @@ VALUE io_read_ensure(VALUE _arguments) {
}

VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
int descriptor = IO_Event_Selector_io_descriptor(io);

size_t offset = NUM2SIZET(_offset);
size_t length = NUM2SIZET(_length);

void *base;
size_t size;
rb_io_buffer_get_bytes_for_writing(buffer, &base, &size);

if (offset > size) {
return rb_fiber_scheduler_io_result(-1, EINVAL);
} else if (offset == size) {
return rb_fiber_scheduler_io_result(0, 0);
}

base = (char*)base + offset;
size -= offset;

int descriptor = IO_Event_Selector_io_descriptor(io);

struct io_read_arguments io_read_arguments = {
.self = self,
.fiber = fiber,
.io = io,

.flags = IO_Event_Selector_nonblock_set(descriptor),
.descriptor = descriptor,
.buffer = buffer,
.base = base,
.size = size,
.length = length,
.offset = offset,
};

RB_OBJ_WRITTEN(self, Qundef, fiber);
Expand Down Expand Up @@ -689,40 +693,29 @@ struct io_write_arguments {

int descriptor;

VALUE buffer;
// The remaining readable buffer region after applying the requested offset.
const void *base;
size_t size;

// The minimum number of bytes requested by the caller.
size_t length;
size_t offset;
};

static
VALUE io_write_loop(VALUE _arguments) {
struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;

const void *base;
size_t size;
rb_io_buffer_get_bytes_for_reading(arguments->buffer, &base, &size);

size_t length = arguments->length;
size_t offset = arguments->offset;
size_t total = 0;

if (length > size) {
rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
}

// Ensure offset is within the bounds of the buffer to avoid size_t underflow and out-of-bounds pointer arithmetic on (char *)base + offset.
if (offset > size) {
return rb_fiber_scheduler_io_result(-1, EINVAL);
}

size_t maximum_size = size - offset;
size_t maximum_size = arguments->size;
while (maximum_size) {
ssize_t result = write(arguments->descriptor, (char*)base+offset, maximum_size);
ssize_t result = write(arguments->descriptor, (char*)arguments->base+total, maximum_size);

if (result > 0) {
total += result;
offset += result;
if ((size_t)result >= length) break;
maximum_size -= result;
length -= result;
} else if (result == 0) {
break;
Expand All @@ -731,8 +724,6 @@ VALUE io_write_loop(VALUE _arguments) {
} else {
return rb_fiber_scheduler_io_result(-1, errno);
}

maximum_size = size - offset;
}

return rb_fiber_scheduler_io_result(total, 0);
Expand All @@ -748,21 +739,38 @@ VALUE io_write_ensure(VALUE _arguments) {
};

VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
int descriptor = IO_Event_Selector_io_descriptor(io);

size_t length = NUM2SIZET(_length);
size_t offset = NUM2SIZET(_offset);

const void *base;
size_t size;
rb_io_buffer_get_bytes_for_reading(buffer, &base, &size);

if (length > size) {
rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
}

if (offset > size) {
return rb_fiber_scheduler_io_result(-1, EINVAL);
} else if (offset == size) {
return rb_fiber_scheduler_io_result(0, 0);
}

base = (const char*)base + offset;
size -= offset;

int descriptor = IO_Event_Selector_io_descriptor(io);

struct io_write_arguments io_write_arguments = {
.self = self,
.fiber = fiber,
.io = io,

.flags = IO_Event_Selector_nonblock_set(descriptor),
.descriptor = descriptor,
.buffer = buffer,
.base = base,
.size = size,
.length = length,
.offset = offset,
};

RB_OBJ_WRITTEN(self, Qundef, fiber);
Expand Down
Loading
Loading