Alvaro Herrera <alvherre@2ndquadrant.com> writes:
> Gustavo Lopes wrote:
>> ... Why wouldn't postgres retry on EINTR or even
>> allow return values of write() lower than nbytes (and then continue in a
>> loop).
> I happened to notice this report from 15 months ago, which didn't get
> any response. Did you find a solution to this problem? I would first
> blame btrfs, mostly because I've never heard of anyone with this problem
> on more mainstream filesystems. As I recall, we use SA_RESTART almost
> everywhere so we don't expect EINTR anywhere.
On my RHEL6 box, the signal(7) man page specifically states that write()
to a disk file will not return EINTR if interrupted by a signal handler
with SA_RESTART set:
If a blocked call to one of the following interfaces is interrupted by
a signal handler, then the call will be automatically restarted after
the signal handler returns if the SA_RESTART flag was used; otherwise
the call will fail with the error EINTR:
* read(2), readv(2), write(2), writev(2), and ioctl(2) calls on
"slow" devices. A "slow" device is one where the I/O call may
block for an indefinite time, for example, a terminal, pipe, or
socket. (A disk is not a slow device according to this defini-
tion.) If an I/O call on a slow device has already transferred
some data by the time it is interrupted by a signal handler, then
the call will return a success status (normally, the number of
bytes transferred).
We set SA_RESTART on every signal that we set an interrupt handler for.
So it's hard to avoid the conclusion that btrfs has broken the API
contract specified by signal(7).
A bit of googling suggests that at least one such case used to exist
in btrfs but has been fixed:
http://linux-btrfs.vger.kernel.narkive.com/CbodH9VP/patch-btrfs-don-t-return-eintr
I wonder what kernel version the OP was using.
regards, tom lane