[SPARK-4107] Fix incorrect handling of read() and skip() return values

`read()` may return fewer bytes than requested; when this occurred, the old
code would silently return less data than requested, which might cause stream
corruption errors.
I think that catching OutOfMemoryError is inconsistent with the rest of the code base.  The only places where we catch it are for the purposes of logging more information about why an executor died.

I don't think that any of the changes that I've made here are inconsistent with the old implementation: if we fail to fetch, we still return None, since ByteStreams.readFully throws IOException when it encounters errors.

Besides, couldn't the OOM have occurred due to some other thread starving this one of memory?