Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 01 Nov 2000 21:09:12 +0200
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        John Polstra <jdp@polstra.com>
Cc:        current@FreeBSD.org, obrien@FreeBSD.org, deischen@FreeBSD.org
Subject:   Re: ABI is broken??
Message-ID:  <3A006A58.E8315ABA@FreeBSD.org>
References:  <3A005026.47B9978C@FreeBSD.org> <200011011835.eA1IZl207585@vashon.polstra.com>

next in thread | previous in thread | raw e-mail | index | archive | help
John Polstra wrote:

> In article <3A005026.47B9978C@FreeBSD.org>,
> Maxim Sobolev  <sobomax@FreeBSD.ORG> wrote:
> >
> > I'm not sure what exactly caused this behaviour (I can guess two potential
> > victims: O'Brien's changes in crt stuff and recent Polstra's changes in
> > libgcc_r), but it seems that some programs built on the previous -current from
> > 27 October immediately segfault when I'm trying to run then on system installed
> > from today's sources. The segfault disappeared when I recompiled affected
> > program. With this message I'm attaching short backtrace.
> [...]
> > Program received signal SIGSEGV, Segmentation fault.
> > 0x287de417 in pthread_mutex_lock () from /usr/lib/libc_r.so.4
> > (gdb) bt
> > #0  0x287de417 in pthread_mutex_lock () from /usr/lib/libc_r.so.4
> > #1  0x806e782 in __register_frame_info ()
> > #2  0x287a3137 in _init () from /usr/lib/libc_r.so.4
> > #3  0x2879ffe5 in _init () from /usr/lib/libc_r.so.4
> > #4  0x280797fd in _rtld () from /usr/libexec/ld-elf.so.1
>
> Here are all the random facts which, when put together, explain what
> is going on.
>
> Your old application was (like all -pthread programs) linked
> with "/usr/lib/libgcc_r.a".  That library contains a function
> "__register_frame_info" which uses some of the facilities of the
> pthreads library "libc_r".
>
> The pthreads library has to be initialized before it can be used, by
> a call to _thread_init.  If some functions such as pthread_mutex_lock
> are called before the library has been initialized, a segmentation
> violation results.
>
> _thread_init is called automatically from libc_r's _init function
> when the dynamic linker loads the library.  Unfortunately, that
> isn't early enough.  libgcc_r is the first thing to be initialized,
> and it calls pthread_mutex_lock before _thread_init has been called.
> Or rather I should say that OLD versions of libgcc_r did that --
> because they were buggy.
>
> In other words, your old application was linked with a buggy version
> of libgcc_r, but it didn't become apparent until now.
>
> It didn't become apparent until now because our crtbegin.o and
> crtend.o were also buggy.  They failed to call __register_frame_info.
> This was a problem for C++ programs using exceptions, especially when
> the gcc port was used and DWARF2 exception handling was selected.
>
> Now we have fixed crtbegin.o and crtend.o, and we have fixed
> libgcc_r.a.  But it causes problems for your old application because
> the new crtbegin.o and crtend.o (linked into the new shared libraries
> such as libc_r) call __register_frame_info in your old, buggy,
> statically linked libgcc_r.a.
>
> Are you dizzy yet?  To sum up, your old executable contains the bug but
> it wasn't triggered until the recent changes.
>
> Now, what can or should we do about this?  Arguably we should simply
> say in the release notes, "Relink your old multithreaded applications.
> They had a bug which is now fixed."  But if there are binary-only
> commercial apps which exhibit the problem, this solution is useless.
> I don't know whether there are any such apps, but I doubt it.  N.B.,
> Linux apps don't count because they were never linked with our
> libgcc_r in the first place.
>
> Or we can try to work around it, but there aren't any perfectly nice
> ways to do so.  Here are some possibilities:
>
> - Put a hack in the threads library so that whenever
>   pthread_mutex_lock is called it checks to make sure that the
>   threads library has been initialized, and if not, it calls
>   _thread_init.  This is a poor solution because it adds overhead to
>   a rather performance-critical function -- though admittedly the
>   overhead is very small.  Another potential problem is that there
>   could be a race condition if several threads all called
>   pthread_mutex_lock at once before the threads library had been
>   initialized.  I don't think the race condition would materialize,
>   though, since the first call would come from libgcc_r, well before
>   the application had gotten control.
>
> - Put a hack into the dynamic linker to call _thread_init very early
>   if that symbol was defined.  I like this solution even less,
>   because it's too hackish.  The dynamic linker isn't the place for
>   special hooks like that.
>
> - Put a hack into crtbegin.o or crtend.o.  But we are using the
>   standard GNU versions of these, and I really really don't want to
>   change that.  In any case, it's the wrong place for the
>   work-around.
>
> Overall I would lean toward putting the hack into pthread_mutex_lock.
> Comments?

Huh, why we can't just bump libc_r version number and put older (buggy) version into
lib/compat as usually? This would not require any ugly hacks at all.

-Maxim



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3A006A58.E8315ABA>