Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!amdcad!sun!snafu!lm From: lm@snafu.Sun.COM (Larry McVoy) Newsgroups: comp.unix.wizards Subject: Re: The 4.3 BSD awrite() solution Message-ID: <131606@sun.Eng.Sun.COM> Date: 10 Feb 90 00:34:56 GMT References: <1055.18:35:28@stealth.acf.nyu.edu> <131445@sun.Eng.Sun.COM> <6068:00:23:14@stealth.acf.nyu.edu> Sender: news@sun.Eng.Sun.COM Reply-To: lm@sun.UUCP (Larry McVoy) Distribution: usa Organization: Sun Microsystems, Mountain View Lines: 74 In article <6068:00:23:14@stealth.acf.nyu.edu> brnstnd@stealth.acf.nyu.edu (Dan Bernstein) writes: >Larry, why don't you at least test the code before asserting that it >doesn't work? I've now run my async library through a rather thorough >series of tests. It works perfectly. aread() and awrite() don't block. > >Your theoretical error is the assertion that a system call can't be >interrupted by a signal (except in an obscure situation, where you >consider the behavior to be in error). But a blocked system call can >be interrupted. That's why siginterrupt() exists. > >Try compiling this code and feeding it into various situations. Try it >with the interrupt flag changed from 1 to 0. Try it with write() instead >of awrite(). Try similar tests with reading. You'll become a believer too. > >#include >#include >#include "async.h" > >main() >{ > char buf[100000]; > > siginterrupt(SIGALRM,1); /* this should be in the async library, I guess */ > fprintf(stderr,"%d\n",awrite(1,buf,sizeof(buf))); >} > >Here are a few tests I tried on a Sun with the above program: > >kramden% ./astest > /dev/null >100000 >kramden% ./astest | cat | wc >4096 > 0 0 4096 First of all, you're right, I was thinking about restarting the system call which only happens if they haven't moved any data. As you pointed out, partially complete system calls (basically read and write) will allow themselves to be interrupted part way through (if you remember the analogy in the last message, this is like allowing "blockmove R0,R1,R3" to be interrupted, whereas you wouldn't allow "inc R0" to be interrupted.) So let's consider your stuff again. You claim that you've implemented awrite(). So what's awrite()? Well, in my mind, awrite(fd, buf, n) should start the I/O and return "n" (it would be nice if you could get status, but you can't with writes either...). The I/O should all go out unless there is some sort of error condition (no mem, bad fd, whatever). That is not at all what you have. You've got a very perverse way to do non-blocking writes. If that's what you want why not implement it like so: awrite(fd, buf, n) void *buf; unsigned n; { fcntl(fd, F_SETFL, O_NONBLOCK); return (write(fd, buf, n)); } Well, I suppose that you could argue that this won't work on disk files (and it won't, at least not in the SunOS code I looked at). But for disk files you obviously don't care - they are async anyway, so you're only interested in pipes/sockets/etc. And those sorts of things support non-blocking I/O in all sorts of ways. So... My point is basically the same. This is *not* an implementation of awrite() by any reasonable definition - it fails to send all the data through. I'm not saying that this has no use, but I am saying (a) this is not an asynchronous write, and (b) you can get the same behavior in a much cleaner way by using O_NONBLOCK. --- What I say is my opinion. I am not paid to speak for Sun, I'm paid to hack. Besides, I frequently read news when I'm drjhgunghc, err, um, drunk. Larry McVoy, Sun Microsystems (415) 336-7627 ...!sun!lm or lm@sun.com