From 50966583f6b72a2149a77d13d5977f1947c8d89c Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 30 Jan 2018 17:26:37 +0100 Subject: [PATCH] noux: handle short writes in the libc plugin Fixes #2661 --- repos/ports/src/lib/libc_noux/plugin.cc | 4 +-- repos/ports/src/noux/io_channel.h | 16 ++++++------ repos/ports/src/noux/pipe_io_channel.h | 17 +++--------- repos/ports/src/noux/syscall.cc | 30 ++++++---------------- repos/ports/src/noux/terminal_io_channel.h | 3 +-- repos/ports/src/noux/vfs_io_channel.h | 3 +-- 6 files changed, 23 insertions(+), 50 deletions(-) diff --git a/repos/ports/src/lib/libc_noux/plugin.cc b/repos/ports/src/lib/libc_noux/plugin.cc index 020617ea2..29ecfe50b 100644 --- a/repos/ports/src/lib/libc_noux/plugin.cc +++ b/repos/ports/src/lib/libc_noux/plugin.cc @@ -1263,8 +1263,8 @@ namespace { } } - count -= curr_count; - src += curr_count; + count -= sysio()->write_out.count; + src += sysio()->write_out.count; } return orig_count; } diff --git a/repos/ports/src/noux/io_channel.h b/repos/ports/src/noux/io_channel.h index 6154b744a..82302c086 100644 --- a/repos/ports/src/noux/io_channel.h +++ b/repos/ports/src/noux/io_channel.h @@ -72,14 +72,14 @@ class Noux::Io_channel : public Reference_counter virtual Io_channel_backend *backend() { return nullptr; } - virtual bool write(Sysio &sysio, size_t &offset) { return false; } - virtual bool read(Sysio &sysio) { return false; } - virtual bool fstat(Sysio &sysio) { return false; } - virtual bool ftruncate(Sysio &sysio) { return false; } - virtual bool fcntl(Sysio &sysio) { return false; } - virtual bool dirent(Sysio &sysio) { return false; } - virtual bool ioctl(Sysio &sysio) { return false; } - virtual bool lseek(Sysio &sysio) { return false; } + virtual bool write(Sysio &sysio) { return false; } + virtual bool read(Sysio &sysio) { return false; } + virtual bool fstat(Sysio &sysio) { return false; } + virtual bool ftruncate(Sysio &sysio) { return false; } + virtual bool fcntl(Sysio &sysio) { return false; } + virtual bool dirent(Sysio &sysio) { return false; } + virtual bool ioctl(Sysio &sysio) { return false; } + virtual bool lseek(Sysio &sysio) { return false; } /** * Return true if an unblocking condition of the channel is satisfied diff --git a/repos/ports/src/noux/pipe_io_channel.h b/repos/ports/src/noux/pipe_io_channel.h index 4fe106fc4..654035c90 100644 --- a/repos/ports/src/noux/pipe_io_channel.h +++ b/repos/ports/src/noux/pipe_io_channel.h @@ -242,21 +242,10 @@ class Noux::Pipe_sink_io_channel : public Io_channel return wr && _pipe->any_space_avail_for_writing(); } - bool write(Sysio &sysio, size_t &offset) override + bool write(Sysio &sysio) override { - /* - * If the write operation is larger than the space available in - * the pipe buffer, the write function is successively called - * for different portions of original write request. The - * current read pointer of the request is tracked via the - * 'count' in/out argument. If completed, 'count' equals - * 'write_in.count'. - */ - - /* dimension the pipe write operation to the not yet written data */ - size_t curr_count = _pipe->write(sysio.write_in.chunk + offset, - sysio.write_in.count - offset); - offset += curr_count; + sysio.write_out.count = _pipe->write(sysio.write_in.chunk, + sysio.write_in.count); return true; } diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc index 369b4e932..f81272b22 100644 --- a/repos/ports/src/noux/syscall.cc +++ b/repos/ports/src/noux/syscall.cc @@ -50,31 +50,17 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) case SYSCALL_WRITE: { - size_t const count_in = _sysio.write_in.count; + Shared_pointer io = _lookup_channel(_sysio.write_in.fd); - for (size_t offset = 0; offset != count_in; ) { + if (!io->nonblocking()) + _block_for_io_channel(io, false, true, false); - Shared_pointer io = _lookup_channel(_sysio.write_in.fd); + if (io->check_unblock(false, true, false)) { + /* 'io->write' is expected to update '_sysio.write_out.count' */ + result = io->write(_sysio); + } else + _sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT; - if (!io->nonblocking()) - _block_for_io_channel(io, false, true, false); - - if (io->check_unblock(false, true, false)) { - /* - * 'io->write' is expected to update - * '_sysio.write_out.count' and 'offset' - */ - result = io->write(_sysio, offset); - if (result == false) - break; - } else { - if (result == false) { - /* nothing was written yet */ - _sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT; - } - break; - } - } break; } diff --git a/repos/ports/src/noux/terminal_io_channel.h b/repos/ports/src/noux/terminal_io_channel.h index 9686a1668..7b3f633c9 100644 --- a/repos/ports/src/noux/terminal_io_channel.h +++ b/repos/ports/src/noux/terminal_io_channel.h @@ -66,7 +66,7 @@ struct Noux::Terminal_io_channel : Io_channel } } - bool write(Sysio &sysio, size_t &offset) override + bool write(Sysio &sysio) override { size_t const count = min(sysio.write_in.count, sizeof(sysio.write_in.chunk)); @@ -74,7 +74,6 @@ struct Noux::Terminal_io_channel : Io_channel _terminal.write(sysio.write_in.chunk, count); sysio.write_out.count = count; - offset = count; return true; } diff --git a/repos/ports/src/noux/vfs_io_channel.h b/repos/ports/src/noux/vfs_io_channel.h index 72b01e5a8..043059ba5 100644 --- a/repos/ports/src/noux/vfs_io_channel.h +++ b/repos/ports/src/noux/vfs_io_channel.h @@ -93,7 +93,7 @@ struct Noux::Vfs_io_channel : Io_channel _fh->ds().close(_fh); } - bool write(Sysio &sysio, size_t &offset) override + bool write(Sysio &sysio) override { Vfs::file_size count = sysio.write_in.count; Vfs::file_size out_count = 0; @@ -117,7 +117,6 @@ struct Noux::Vfs_io_channel : Io_channel _fh->advance_seek(out_count); sysio.write_out.count = out_count; - offset = out_count; return true; }