Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can read(2) return zero when not at EOF?

Tags:

c++

linux

eof

According to the man page for read(2), it only returns zero when EOF is reached.

However, It appears this is incorrect and that it may sometimes return zero, perhaps because the file is not ready to be read yet? Should I call select() to see if it is ready before reading a file from disk?

Note that nBytes is: 1,445,888

Some sample code:

fd_set readFdSet;
timeval timeOutTv;

timeOutTv.tv_sec = 0;
timeOutTv.tv_usec = 0;

// Let's see if we'll block on the read.
FD_ZERO(&readFdSet);
FD_SET(fd, &readFdSet);

int selectReturn = ::select(fd + 1, &readFdSet, NULL, NULL, &timeOutTv);

if (selectReturn == 0) {
  // There is still more to read.
  return false; // But return early.
} else if (selectReturn < 0) {
  clog << "Error: select failure: " << strerror(errno) << endl;
  abort();
} else {
  assert(FD_ISSET(fd, &readFdSet));

  try {
    const int bufferSizeAvailable = _bufferSize - _availableIn;

    if (_availableIn) {
      assert(_availableIn <= _bufferSize);

      memmove(_buffer, _buffer + bufferSizeAvailable, _availableIn);
    }

    ssize_t got = ::read(fd, _buffer + _availableIn, bufferSizeAvailable);

    clog << " available: " << bufferSizeAvailable << " availableIn: "
         << _availableIn << " bufferSize: " << _bufferSize << " got "
         << got << endl;

    return got == 0;
  } catch (Err &err) {
    err.append("During load from file.");
    throw;
  }
}

The output reads (when it fails with no data read):

available: 1445888 availableIn: 0 bufferSize: 1445888 got: 0

This is running on centos4 32 bit as a virtual machine using VMware Server 1.0.10. The file system being read is local to the virtual machine. The host machine is windows server 2008 32 bit.

The uname -a says:

Linux q-centos4x32 2.6.9-89.0.25.ELsmp #1 SMP Thu May 6 12:28:03 EDT 2010 i686 i686 i386 GNU/Linux

I notice that the link http://opengroup.org/onlinepubs/007908775/xsh/read.html given below states:

The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal...

If a read() is interrupted by a signal before it reads any data, it will return -1 with errno set to [EINTR].

If a read() is interrupted by a signal after it has successfully read some data, it will return the number of bytes read. 

So, perhaps I am getting a signal interrupting the read and thus the value returned is zero because of either a bug or it thinks zero bytes were read?

like image 647
WilliamKF Avatar asked Jun 19 '10 03:06

WilliamKF


People also ask

What does read return at EOF?

Upon reading end-of-file, zero is returned. Otherwise, a -1 is returned and the global variable errno is set to indicate the error.

What is the return value of read in C?

In POSIX C programs only, if read() is interrupted by a signal, the effect is one of the following: If read() has not read any data yet, it returns -1 and sets errno to EINTR. If read() has successfully read some data, it returns the number of bytes it read before it was interrupted.

How does read () work in C?

The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of existing data in the file.

Is read system call blocking?

Because client socket is configured to be nonblocking, read is incapable of blocking.


3 Answers

After some research, there actually are some circumstances under which it will return 0 that you might not think of as being "EOF".

For the gritty details, see the POSIX definition for read(): http://opengroup.org/onlinepubs/007908775/xsh/read.html

Some notable ones are if you ask it to read 0 bytes -- double check that you're not accidentally passing 0 to it -- and reading past the end of the "written" portion of the file (you can actually seek past the end of the file, which "extends" the file with zeroes if you write there, but until you do, "EOF" is still at the end of the already-written portion).

My best guess is that you're getting into a timing problem somewhere. Some questions you need to ask are "How are these files being written?" and "Am I sure they're not zero-length when I try to read them?". For the second one, you could try running a stat() on the file before reading it to see what its current size is.

like image 172
Nicholas Knight Avatar answered Sep 23 '22 18:09

Nicholas Knight


The only other case that I can think of read() returning 0 is if you pass in nbytes as 0; sometimes that can happen if you're passing in the size of something or other as a parameter. Could that be what's happening right now?

If the file is not ready to be read, what should happen is read returns -1 and errno is set to EAGAIN.

like image 23
Adrian Petrescu Avatar answered Sep 22 '22 18:09

Adrian Petrescu


Figured it out! I had an Uninitialized Memory Read (UMR) and was incorrectly seeking to the end of the file.

like image 43
WilliamKF Avatar answered Sep 25 '22 18:09

WilliamKF