On Thu, Nov 17, 2005 at 03:59:58PM +0100, Michael Kerrisk wrote: > > It appears you *have* to open in blocking mode in order to > > open a leased file at all, > > Yes. > > > but that's not clear from the description. > > Again, I would say that's fairly clear from the man page: > if the open() call returns (i.e., fails) with EWOULDBLOCK, > then clearly the file was not opened. But again, it might > help to add a little more text. > > > It wouldn't be so bad to open in blocking mode since a lease is > > guaranteed > > to be broken after a certain timeout. But a naive implementation would > > introduce a security hole since the file might be replaced by surprise > > with a FIFO, which has no open timeout at all. > > I do not understand this last piece.
The above three things tie together: if you're correct and the lease-breaking steps are followed even with O_NONBLOCK, it's obvious that you could *potentially* be able to open a leased file with O_NONBLOCK eventually, by following steps like this: - open() -> EWOULDBLOCK - wait a while - open() -> success That's because the lease *starts* to get broken on the first open(), and probably is finished being broken by your second or third try. So the first claim above, that you *have* to open in blocking mode, is not strictly true. It would be true if opening with O_NONBLOCK definitely *doesn't* ask to start the lease breaking-steps; that's the part I thought was unclear. (The clarification you added about it is good, assuming it's correct.) But essentially, even if this might work eventually, it's unsafe, because what *might* happen is this: - open() -> EWOULDBLOCK - lease gets broken - lease gets reacquired - open() -> EWOULDBLOCK - ... The only way to guarantee that you'll ever get to open the file within some reasonable time is to open it in blocking mode. This might be a very common case. I know that if I was writing a lease-using program, and I knew that giving up my lease was part of a chain of events that guaranteed the next guy he *could* open the file immediately, and the open succeeded immediately when I gave up my lease, then I might simply give up the lease and then blocking-reacquire it. That minimizes the time I *don't* have my lease, while supposedly not getting in anyone's way. And so: > If the lease breaker's blocked open() or truncate() is > interrupted by a signal handler, then the system call > fails with the error EINTR, but the other steps still > occur as described above. If the lease breaker is > killed by a signal while blocked in open() or trun- > cate(), then the other steps still occur as described > above. If the lease breaker specifies the O_NONBLOCK > flag when calling open(), then the call immediately > fails with the error EWOULDBLOCK, but the other steps > still occur as described above. In this paragraph, which generally I find good, you might want to caution that although the steps still occur with O_NONBLOCK, you introduce a race condition and are not guaranteed to ever successfully open the file unless you open it in blocking mode. So I might do this: - open(O_NONBLOCK) -> EWOULDBLOCK - (no special time delay) - open(^O_NONBLOCK) -> success within a short time And that leads me to explain my final point about the security problem, which doesn't seem to have an obvious workaround if you use the above method: - open(O_NONBLOCK) -> EWOULDBLOCK - someone replaces the leased file with a fifo - open(^O_NONBLOCK) -> blocks forever My totally nonblocking daemon may be forced to block in order to acquire a lease, but the blocking period has a guaranteed maximum, so it's not so bad. However, the file might suddenly become a fifo, which has no guaranteed maximum timeout, and that's bad. At this point the workarounds are getting slightly crazy, but it looks like a fork()-and-open()-with-timeout mechanism might be the only safe way to go. Not sure if you care to document anything to this extent, but my point is that you might caution about O_NONBLOCK and leases; basically it's not very useful because there's no guarantee it'll ever work. Have fun, Avery -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]