File::Read does not read everything

Hello,

I am using LLDB 3.9 on Linux Ubuntu. I am loading a 5GiB core which is located on Windows file share mounted on Linux via mount.cifs. I see that we successfully allocated memory and are trying to fill it in one read. Unfortunately pread returns 2GiB and we never check for short read here.

I think we could combine this code with previous block “#if defined (MAX_READ_SIZE)” if we simply check for short read here (bytes_read too small) and loop until all the buffer is filled.

Thanks,

Eugene

#ifndef _WIN32
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
{
ssize_t bytes_read = -1;
do
{
bytes_read = ::pread (fd, buf, num_bytes, offset);
} while (bytes_read < 0 && errno == EINTR);

if (bytes_read < 0)
{
num_bytes = 0;
error.SetErrorToErrno();
}
else
{
offset += bytes_read;
num_bytes = bytes_read;
}
}

It is probably best to make the code loop as long as "bytes_reads > 0" and we haven't read "num_bytes" yet. The darwin kernel has a INT32_MAX read size which gets set to MAX_READ_SIZE, but we need to do that because if you try to read more than that it reads nothing. So MAX_READ_SIZE is more for the case where the read will outright fail if given a byte size that is too large. Feel free to submit a patch that can keep calling pread correctly in a loop as long as bytes_read > 0.

Greg

Here is what I am running now:

diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index 89587a9…a4ac25e 100644
— a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -771,21 +771,34 @@ File::Read (void *buf, size_t &num_bytes, off_t &offset)
int fd = GetDescriptor();
if (fd != kInvalidDescriptor)
{

  • ssize_t bytes_read = -1;
  • do
  • size_t bytes_left = num_bytes;
  • num_bytes = 0;
  • char pos = (char)buf;
  • while (bytes_left > 0)
    {
  • bytes_read = ::pread (fd, buf, num_bytes, offset);
  • } while (bytes_read < 0 && errno == EINTR);
  • ssize_t bytes_read = -1;
  • do
  • {
  • bytes_read = ::pread (fd, pos, bytes_left, offset);
  • } while (bytes_read < 0 && errno == EINTR);
  • if (bytes_read < 0)
  • {
  • num_bytes = 0;
  • error.SetErrorToErrno();
  • }
  • else
  • {
  • offset += bytes_read;
  • num_bytes = bytes_read;
  • if (bytes_read < 0)
  • {
  • num_bytes = 0;
  • error.SetErrorToErrno();
  • break;
  • }
  • else if (bytes_read == 0)
  • {
  • break;
  • }
  • else
  • {
  • offset += bytes_read;
  • num_bytes += bytes_read;
  • bytes_left -= bytes_read;
  • pos += bytes_read;
  • }
    }
    }
    else

Can you upload a diff (with context) to phabricator and add lldb-commits as a subscriber and myself / Greg as reviewers?

Sorry for noob’s question: what is “phabricator”?

Sure, I will do it as soon as I understand what you want me to do :slight_smile:

http://reviews.llvm.org. Create an account there and upload patch

Done. https://reviews.llvm.org/D25712