On Sun, Aug 19, 2012 at 03:26:36PM +0300, Konstantin Belousov wrote:
> On Fri, Aug 17, 2012 at 06:08:47PM +0200, Jilles Tjoelker wrote:
> > On Fri, Aug 17, 2012 at 03:43:12PM +0300, Konstantin Belousov wrote:
> > > On Fri, Aug 17, 2012 at 12:39:33AM +0200, Jilles Tjoelker wrote:
> > > > On Thu, Aug 16, 2012 at 02:44:26PM +0300, Konstantin Belousov wrote:
> > > > > BTW, returning to Jilles proposal, can we call vfork() only for
> > > > > single-threaded parent ? I think it gives good boost for
> > > > > single-threaded
> > > > > case, and also eliminates the concerns of non-safety.
> > > > This would probably fix the safety issues but at a price. There is a
> > > > correlation between processes so large that they benefit greatly from
> > > > vfork and threaded processes.
> > > Ok, so I will continue with my patch.
> > > > On the other hand, I think direct calls to vfork() in applications are
> > > > risky and it may not be possible to support them safely in all
> > > > circumstances. However, if libc is calling vfork() such as via popen(),
> > > > system() or posix_spawn(), it should be possible even in a
> > > > multi-threaded process. In that case, the rtld and libthr problems can
> > > > be avoided by using aliases with hidden visibility for all functions the
> > > > vforked child needs to call (or any other method that prevents
> > > > interposition and hard-codes a displacement into libc.so).
> > > I do not see how using any aliases could help there. Basically, if mt
> > > process is not single-threaded for vfork, you can have both some parent
> > > thread and child enter rtld. This is complete mess.
> > If libc calls a function with hidden visibility, this proceeds directly
> > (not via the PLT) and rtld is not involved.
> Oh, so you are only concerned with libc there ?
> If spending so much efforts on this issue, IMO it is pity to only fix
> libc and not fix vfork for all consumers.
True. If vfork can be fixed more generally without too much penalty, it
is better to do that. And it looks like that is possible, including
detecting unexpected kills, see below.
> > Several ways to do this are in section 2.2.7 Avoid Using Exported
> > Symbols of Ulrich Drepper's dsohowto. One of them is something like
> > extern __typeof(next) next_int
> > __attribute((alias("next"), visibility("hidden")));
> > in the same source as the definition of the function
> > int next(void) { ...; }
> > As Drepper notes, the visibility attribute is not strictly required if a
> > version script keeps the symbol local but it might lead to better code.
> > At least on i386, though, the optimal direct near call instruction is
> > generated even without it. For example, _nsdispatch() calls
> > libc_dlopen() (kept local by the version script) without going through
> > the PLT (from the output of objdump -dS on the libc.so.7 in /usr/obj).
> I am not confident, so this might be a hallucination, but 'optimization'
> in the recent gnu ld might rewrite the call target to avoid PLT when
> symbol visibility is hidden.
If symbol visibility is hidden, rtld does not know about the symbol's
name; therefore, the only way ld can make it work is to make the call
instruction point directly at the called function, not to a PLT entry.
Different from what I wrote earlier, on i386, there is still a penalty
in omitting the visibility attribute: the compiler will generate code to
load %ebx which may not be necessary.
> > In the assembler syscall stubs using code from lib/libc/arch/SYS.h this
> > can be done by adding another .set (we currently have foo, _foo and
> > __sys_foo for a syscall foo; some syscalls have only _foo and
> > __sys_foo) such as __syshidden_foo. The ones that are actually used
> > then need prototypes (similar to the __sys_* ones in lib/libthr/?).
> > For some reason, the symbol .cerror (HIDENAME(cerror)) is also exported.
> > Either this should be kept local or a local uninterposable alias should
> > be added and used (as with the syscalls).
I sent a patch for .cerror (i386 only) in a new mailing list thread.
> > The function __error() (to get errno's address for the current thread)
> > is and must be called via the PLT (because libthr is separate).
> > Therefore, we should ensure it is called at least once before vfork so
> > calls in the child do not involve rtld. The implementations for the
> > various architectures use the TLS register (or memory location for ARM),
> > so they seem safe.
> > This should suffice to fix posix_spawn() but the _execvpe() used by
> > posix_spawnp also uses various string functions. If not all of these
> > have already been called earlier, this will not work. Making calls to
> > them not go through the PLT seems fairly hard, even though it would make
> > sense in general, so perhaps I should instead reimplement it such that
> > the parent does almost all of the work.
> > An alternative is to write the core of posix_spawn() in assembler using
> > system calls directly but I woul