Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Rainer Weikusat Newsgroups: comp.os.linux.development.apps,comp.unix.programmer Subject: Re: Linux O_NONBLOCK bug/ quirk Followup-To: comp.unix.programmer Date: Wed, 16 Apr 2014 13:36:05 +0100 Lines: 32 Message-ID: <87y4z5tpsa.fsf@sable.mobileactivedefense.com> References: <878urvu0gx.fsf@sable.mobileactivedefense.com> <877g6pv6tc.fsf@sable.mobileactivedefense.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: individual.net k9479OeE3JThxg1f9bI9xQdOogA4azs4Y7v8/vM/N5i96gIZA= Cancel-Lock: sha1:czBazJ8e6kuPqgAllIqIWjXCy8Q= sha1:1lsWl6XwmvJNPs88NwLRRpWyORM= User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) Xref: csiph.com comp.os.linux.development.apps:694 comp.unix.programmer:5304 Rainer Weikusat writes: > Lusotec writes: > > [demonstration of Linux bug] > >> a fcntl must affect a already running operations. I think this >> is very problematic. > > NB: This is crossposted to comp.unix.programmer with a followup-to set > as it is (in my opinion) mostly about POSIX/ UNIX(*) implementation > quirks. > > NB^2: This has been tested on Linux 3.2.9 without the recent "nonblocking fix" > applied, I'm totally innocent of this mess. > > As someone named John McCue discovered, the fcntl does actually affect > the running operation, although in rather strange ways: In case a > non-blocking read which happened to be blocking is interrupted (this > shouldn't happen because it shouldn't block aka 'go to sleep in the > kernel until some external event occurs'), the kernel tries to hide that > by silently returning an EAGAIN error instead of an EINTR error. But it > doesn't keep track of which calls were blocking and which > weren't. The net effect is that a blocking call supposed to be restarted > in case it was interrupted by a signal actually aborts with EAGAIN since > glibc "doesn't expect that" I was wrong about that: The behaviour is actually correct, although somewhat counter-intuitive: The read is interrupted. It is then restarted by the C library and fails with EAGAIN because O_NONBLOCK is now set for the file descriptor in question. Minus the 'SIGCONT interrupts' quirk, this is also the behavour in the other case.