On Thu, Sep 10, 2009 at 1:01 PM, Dustin J. Mitchell <dus...@zmanda.com>
wrote:
> On Thu, Sep 10, 2009 at 2:29 PM, Philip Guenther<guent...@gmail.com> wrote:
>> It happens at initialization time of libpthread and is undone at exit
>> and exec.  It applies to all fds.  There is no manpage, as it's not
>> (supposed to be) application visible.
>
> OK, so basically this is an OpenBSD/pthread bug.  I'm still sort of
> shell-shocked here.  The idea is that *all* file descriptors are made
> non-blocking, and then the file-descriptor syscalls are wrapped to
> pretend they are blocking.  As long as all of the code operating on
> those "pseudo-blocking" files is using the wrapped syscalls, all is
> well.  However, when one of those files is accessed by a binary not
> linked to libpthread, the illusion breaks down.
>
> Do I have that right?

Yep.


> Why does the fcntl(fd, F_GETFL) fix it?  Does it really fix it, or are
> we just lucky?

The original post wasn't clear where that line was being inserted, as
it said "before the dup2" ...when there were two dup2 calls in the
quoted code.  I'm not 100% clear on the exact sequence of forks,
execs, and fd manipulation (the dup2 in the child is done _after_ the
exec?  Does sendbackup fork before execing dump or do it directly?) so
I can't be sure, but off-hand it looks more like luck than a real fix.
 Can you describe the sequence of operations in more detail?


> This sounds like more of a design bug than a code bug, so I don't
> expect a fix in a 4.5 patch release.  So we'll need to do something to
> work around it in Amanda.  Presumably this is a fairly common problem,
> so what is the usual solution?

Actually, it's a pretty rare problem.  The restrictions that the
standard sets on operations after fork() in a threaded process mean
that relatively few programs tangle in to this that much.  Not linking
with libpthread unless actually necessary helps too.  So there is no
"usual solution".  There was a previous case where the workaround was
to explicitly set a socket to non-blocking before forking (so that the
parent wouldn't reset its state when closing it), but pipes are
already excluded from the logic that was being hit in that case.  (It
was actually the reverse problem then, with the fd was being set back
to blocking behind the threaded process's back.)


Philip Guenther

Reply via email to