Question: short-read while loading .so file

ISHIKAWA,chiaki ishikawa@yk.rim.or.jp
Thu Jun 11 14:44:00 GMT 2015


On 2015/06/10 6:41, Ángel González wrote:
> On 09/06/15 19:03, ISHIKAWA,chiaki wrote:
>> I asked the following question to binutils mailing list first
>> and was advised to post it to libc-alpha. I misunderstood that dynamic
>> loading was handled by a component of linker.
>> Here it goes. The behavior was observed under Debian GNU/Linux.
> (...)
>> While testing how mozilla thunderbird handles "short read", i.e.,
>> a |read| system call that returns prematurely without returning all the
>> octets (subsequent |read|(s) will return the octets eventually),
>
> (...)
>> BTW, such "short read" can occur with remote file system when there is a
>> network issue, etc. Usually, local file system does not cause "short
>> read", but once we go across the net, anything can happen.)
>
> Note that Linux kernel guarantees that you won't receive a partial read
> for a
> "normal" file (although a custom filesystem could return that, as you
> point out),
> so an application developer might claim that such environment isn't
> supported.
> See http://yarchive.net/comp/linux/wakekill.html#4
>
>

Thank you for your comment.

The link points to a thread that took place in August, 2002.

Today, in 2015, POSIX.1-2008 available at

http://pubs.opengroup.org/onlinepubs/

and man page for |read| specifically,describes a slightly different 
semantics.

http://pubs.opengroup.org/onlinepubs/9699919799/

Basically, Single Unix Specification today calls
for old-fashioned BSD-like behavior.

 From the above |read| man page: (marking by "***" is mine.)
--- begin quote ---
Earlier versions of this standard allowed two very different behaviors 
with regard to the handling of interrupts. In order to minimize the 
resulting confusion, it was decided that POSIX.1-2008 should support 
only one of these behaviors. Historical practice on AT&T-derived systems 
was to have read() and write() return -1 and set errno to [EINTR] when 
interrupted after some, but not all, of the data requested had been 
transferred. However, the US Department of Commerce FIPS 151-1
and FIPS 151-2 require the historical BSD behavior, in which read() and
                         *********************************************
write() return the number of bytes actually transferred before the
***********************************************************************
interrupt. If -1 is returned when any data is transferred, it is
***********
difficult to recover from the error on a seekable device and impossible 
on a non-seekable device. Most new implementations support this
                         ****************************************
behavior. The behavior required by POSIX.1-2008 is to return the number
************************************************************************
of bytes transferred.
*********************
--- end quote ---

I was thinking of along the line of "the historical BSD behavior, in 
which read() and write() return the number of bytes actually transferred 
before the interrupt. " and which seems to be supported by modern 
implementation and , and thus want to see dynamic loader
re-read the rest of data if short read occurs.
(As a matter of fact, mozilla thunderbird codebase does handle
short-write cases very well. It detects short write and tries to repeat 
the write until everything is written.
So I suspect the OSs for which it was developed did show behavior of 
POSIX.1-2008 as far as write() is concerned. Short-write occurred there.
It is short-read mozilla thunderbird occasionally mishanldes and that is 
why I was testing it
under simulated short-read condition when I noticed dynamic loading
may suffer from similar short-read.

(Yes, I have noticed that Linus specifically mentioned he doesn't care
about POSIX, but even then it was 2002 and he may have a different 
opinion today, especially to cope with network file system behavior?
I am not talking about LOCAL kernel interrupting local system call 
randomly (most notably read/write calls) which Linus disliked so much,
but here I am talking about read request to the remote file server 
returns a short-read result which a local kernel can't do a thing. It 
has to return the shorter-than-requested # of octets and errno is NOT 
set, I think.)

My analysis of the behavior of dynamic loader (which does not repeat the 
read to read the originally requested amount) may
cause problems for a normal program if the dynamically loading
*.so files from a remote file system causes short read occasionally and 
dynamic loading mechanism does not repeat the read.
Isn't such dynamic loading handled by a routine in glibc?
(Or is it done inside the kernel???)

Where does glibc get used other other than under linux?
I wonder if this behavior of not repeating short read for *.so file
may cause issues on such systems when remote filesystems are used.

Thank you again.

CI





>



More information about the Libc-help mailing list