rb_io_puts
should not write zero length strings. (#7806)
This commit is contained in:
parent
91c004885f
commit
0b2613f443
Notes:
git
2023-05-15 02:14:20 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
34
io.c
34
io.c
@ -1327,16 +1327,17 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
|
|||||||
static ssize_t
|
static ssize_t
|
||||||
rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
|
rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
|
||||||
{
|
{
|
||||||
|
if (!iovcnt) return 0;
|
||||||
|
|
||||||
VALUE scheduler = rb_fiber_scheduler_current();
|
VALUE scheduler = rb_fiber_scheduler_current();
|
||||||
if (scheduler != Qnil) {
|
if (scheduler != Qnil) {
|
||||||
for (int i = 0; i < iovcnt; i += 1) {
|
// This path assumes at least one `iov`:
|
||||||
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[i].iov_base, iov[i].iov_len, 0);
|
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[0].iov_base, iov[0].iov_len, 0);
|
||||||
|
|
||||||
if (!UNDEF_P(result)) {
|
if (!UNDEF_P(result)) {
|
||||||
return rb_fiber_scheduler_io_result_apply(result);
|
return rb_fiber_scheduler_io_result_apply(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct io_internal_writev_struct iis = {
|
struct io_internal_writev_struct iis = {
|
||||||
.th = rb_thread_current(),
|
.th = rb_thread_current(),
|
||||||
@ -2041,7 +2042,7 @@ io_binwritev_internal(VALUE arg)
|
|||||||
while (remaining) {
|
while (remaining) {
|
||||||
long result = rb_writev_internal(fptr, iov, iovcnt);
|
long result = rb_writev_internal(fptr, iov, iovcnt);
|
||||||
|
|
||||||
if (result > 0) {
|
if (result >= 0) {
|
||||||
offset += result;
|
offset += result;
|
||||||
if (fptr->wbuf.ptr && fptr->wbuf.len) {
|
if (fptr->wbuf.ptr && fptr->wbuf.len) {
|
||||||
if (offset < (size_t)fptr->wbuf.len) {
|
if (offset < (size_t)fptr->wbuf.len) {
|
||||||
@ -8914,7 +8915,6 @@ io_puts_ary(VALUE ary, VALUE out, int recur)
|
|||||||
VALUE
|
VALUE
|
||||||
rb_io_puts(int argc, const VALUE *argv, VALUE out)
|
rb_io_puts(int argc, const VALUE *argv, VALUE out)
|
||||||
{
|
{
|
||||||
int i, n;
|
|
||||||
VALUE line, args[2];
|
VALUE line, args[2];
|
||||||
|
|
||||||
/* if no argument given, print newline. */
|
/* if no argument given, print newline. */
|
||||||
@ -8922,22 +8922,30 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out)
|
|||||||
rb_io_write(out, rb_default_rs);
|
rb_io_write(out, rb_default_rs);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
for (i=0; i<argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
|
// Convert the argument to a string:
|
||||||
if (RB_TYPE_P(argv[i], T_STRING)) {
|
if (RB_TYPE_P(argv[i], T_STRING)) {
|
||||||
line = argv[i];
|
line = argv[i];
|
||||||
goto string;
|
|
||||||
}
|
}
|
||||||
if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
|
else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
line = rb_obj_as_string(argv[i]);
|
line = rb_obj_as_string(argv[i]);
|
||||||
string:
|
}
|
||||||
n = 0;
|
|
||||||
args[n++] = line;
|
// Write the line:
|
||||||
if (RSTRING_LEN(line) == 0 ||
|
int n = 0;
|
||||||
!rb_str_end_with_asciichar(line, '\n')) {
|
if (RSTRING_LEN(line) == 0) {
|
||||||
args[n++] = rb_default_rs;
|
args[n++] = rb_default_rs;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
args[n++] = line;
|
||||||
|
if (!rb_str_end_with_asciichar(line, '\n')) {
|
||||||
|
args[n++] = rb_default_rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rb_io_writev(out, n, args);
|
rb_io_writev(out, n, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +170,34 @@ class TestFiberIO < Test::Unit::TestCase
|
|||||||
assert_predicate(o, :closed?)
|
assert_predicate(o, :closed?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_puts_empty
|
||||||
|
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
|
||||||
|
|
||||||
|
i, o = UNIXSocket.pair
|
||||||
|
i.nonblock = false
|
||||||
|
o.nonblock = false
|
||||||
|
|
||||||
|
thread = Thread.new do
|
||||||
|
# This scheduler provides non-blocking `io_read`/`io_write`:
|
||||||
|
scheduler = IOBufferScheduler.new
|
||||||
|
Fiber.set_scheduler scheduler
|
||||||
|
|
||||||
|
Fiber.schedule do
|
||||||
|
# This was causing a segfault on older Ruby.
|
||||||
|
o.puts ""
|
||||||
|
o.puts nil
|
||||||
|
o.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
thread.join
|
||||||
|
|
||||||
|
message = i.read
|
||||||
|
i.close
|
||||||
|
|
||||||
|
assert_equal $/*2, message
|
||||||
|
end
|
||||||
|
|
||||||
def test_io_select
|
def test_io_select
|
||||||
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
|
omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user