delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/01/23/15:33:15

Sender: rich AT phekda DOT freeserve DOT co DOT uk
Message-ID: <3E305173.9E89FA57@phekda.freeserve.co.uk>
Date: Thu, 23 Jan 2003 20:32:52 +0000
From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.23 i586)
X-Accept-Language: de,fr
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Re: readv, writev [PATCH]
References: <Pine DOT SUN DOT 3 DOT 91 DOT 1030123082200 DOT 15630D AT is> <3E2FC531 DOT F37C6D24 AT phekda DOT freeserve DOT co DOT uk> <2427-Thu23Jan2003204136+0200-eliz AT is DOT elta DOT co DOT il>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Eli Zaretskii wrote:
> 
> > Date: Thu, 23 Jan 2003 10:34:25 +0000
> > From: Richard Dawe <rich AT phekda DOT freeserve DOT co DOT uk>
> >
> > Say you write the first part of the data, but then the write for the next
> > part fails. What do you return? The call has failed, but you have written
> > some data. It seems to me that it would be hard for a program to recover
> > gracefully from this, since it doesn't know what has been written
> > to the file.
> 
> What is teh common practice in other implementations?  Like glibc,
> for example?

There are three alternatives in glibc, depending on OS:

(a) Use the system call. (There is one on Linux. This falls back on the POSIX
implementation in certain conditions - too many iovecs in the vector.)

(b) Allocate a chunk of memory, copy all the chunks into it and write them
out. (This is the POSIX implementation.)

(c) Fail and return ENOSYS (function unimplemented).

For (b) there is a comment:

    /* XXX I don't know whether it is acceptable to try writing
       the data in chunks.  Probably not so we just fail here.  */

Please note that I haven't looked at the glibc source before. I was pretty
surprised to find that it uses technique (b)! I looked at glibc 2.2.93
sources.

For option (b) glibc uses alloca for small (< 512K) allocations.

readv has similar code, with a similar "XXX" comment as above for the POSIX
implementation.

> > If writev were to write iov-by-iov and one call failed, it would need to
> > seek to the position that it was at, before writing. This is to ensure:
> >
> > 1. that a retry will overwrite the data;
> > 2. that we read from the position where the writes started.
> 
> I'm not sure I understand this: what retry are we talking about here?

I mean the application retrying the write. (Sorry, I wasn't clear there.)

> Also, read after write requires an lseek, right?

Yes, if you want to read back the data you just wrote.

But if write() fails, then the file pointer is not advanced. Consider writev()
for a vector of 2 entries, if we write() iovec-by-iovec:

Entry 1: write() succeeds
Entry 2: write() fails

If we want to fail writev(), because the second write fails, then we should
seek to the position before writev() was called.

> > * It should cope with non-blocking write calls.
> 
> Is this relevant for DOS?  We don't support non-blocking I/O.

I guess not. I suspect we'd need to update libc in other places to support
non-blocking I/O properly.

I was just thinking back to my libsocket days. libsocket did support
non-blocking I/O. But then libsocket comes with its own readv()/writev()
implementation.
 
I wonder if any other FSEXTs support non-blocking I/O?

> > > Can't you use _read instead?  Is readv supposed to handle text files and
> > > do CRLF->NL conversions?
> > >
> > > The same holds for _write in writev.
> >
> > I assumed that readv, writev were just vector-input versions of read,
> > write and so should have the same CFLF->NL conversion characteristics.
> 
> >From the function's descriptions, it sounds like they are for binary
> data, but I might be mistaken.
[snip]

Typically readv() and writev() are used with sockets, because they're pretty
convenient for that.

> Does anyone know what does Cygwin do in this case?

Cygwin's writev() uses the normal write() call, which CRLF->NL conversion, if
in text mode. See:

http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/syscalls.cc?rev=1.240&content-type=text/x-cvsweb-markup&cvsroot=src
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/fhandler.cc?rev=1.143&content-type=text/x-cvsweb-markup&cvsroot=src

The first file is just the "system call", which ends up going to a Cygwin file
handler. Search for fhandler_base::write and fhandler_base::writev in the
second file.

OK, now I'm slightly embarrassed. This is also the first time I've looked at
the Cygwin source and they seem to use the memory allocation method too.

Bye, Rich =]

-- 
Richard Dawe [ http://www.phekda.freeserve.co.uk/richdawe/ ]

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019