Bug 221423 - gcc std::locale(LocaleName) crashes instead of throwing an exception
Summary: gcc std::locale(LocaleName) crashes instead of throwing an exception
Status: New
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-toolchain mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-11 19:29 UTC by Artyom Beilis
Modified: 2017-08-16 03:42 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Artyom Beilis 2017-08-11 19:29:22 UTC
This simple program crashes "Abort trap (core dumped)" when it either expected to succeed or to catch an exception.


$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc5/gcc/x86_64-portbld-freebsd11.0/5.4.0/lto-wrapper
Target: x86_64-portbld-freebsd11.0
Configured with: /wrkdirs/usr/ports/lang/gcc5/work/gcc-5.4.0/configure --with-build-config=bootstrap-debug --disable-nls --enable-gnu-indirect-function --libdir=/usr/local/lib/gcc5 --libexecdir=/usr/local/libexec/gcc5 --program-suffix=5 --with-as=/usr/local/bin/as --with-gmp=/usr/local --with-gxx-include-dir=/usr/local/lib/gcc5/include/c++/ --with-ld=/usr/local/bin/ld --with-pkgversion='FreeBSD Ports Collection' --with-system-zlib --with-ecj-jar=/usr/local/share/java/ecj-4.5.jar --enable-languages=c,c++,objc,fortran,java --prefix=/usr/local --localstatedir=/var --mandir=/usr/local/man --infodir=/usr/local/info/gcc5 --build=x86_64-portbld-freebsd11.0
Thread model: posix
gcc version 5.4.0 (FreeBSD Ports Collection) 

$ pkg info gcc
gcc-5.4.0_2
Name           : gcc
Version        : 5.4.0_2
Installed on   : Wed Aug  9 03:18:50 2017 IDT
Origin         : lang/gcc
Architecture   : FreeBSD:11:*
Prefix         : /usr/local
Categories     : lang java
Licenses       : 
Maintainer     : gerald@FreeBSD.org
WWW            : http://gcc.gnu.org
Comment        : Meta-port for the default version of the GNU Compiler Collection
Annotations    :
        repo_type      : binary
        repository     : FreeBSD
Flat size      : 17.0B
Description    :
GCC, the GNU Compiler Collection, supports a number of languages.  This
port pulls in gcc5 (or another version-specific port) and defines symlinks
called gcc, g++, and gfortran.

WWW: http://gcc.gnu.org

Gerald Pfeifer <gerald@FreeBSD.org>

$ uname -a
FreeBSD freebsd11 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64


//////////////////

Code:


////////////


#include <iostream>
#include <locale>

int main()
{
        try {
                std::locale l = std::locale("en_US.UTF-8");
        }
        catch(std::exception const &e) {
                std::cerr << e.what() << std::endl;
        }
        catch(...) {
                std::cerr << "Unknown exception " << std::endl;
        }
}
Comment 1 Artyom Beilis 2017-08-11 19:37:59 UTC
For got to add building/running:

$ g++ test.cpp 
$ ./a.out 
Abort trap (core dumped)
Comment 2 Gerald Pfeifer freebsd_committer 2017-08-11 21:31:44 UTC
Might this be related to what was just discussed a few days ago
(related to libsupc++ vs libcxxrt) in PR 221288?
Comment 3 Mark Millard 2017-08-11 22:44:58 UTC
(In reply to Artyom Beilis from comment #1)

The compile/link command did not specify:

-Wl,-rpath=/usr/local/lib/gcc5

and so is likely to get more of a mix of
system and gcc libraries than gcc5 is designed
for.

(That command line option above has details
that assume typical placements of files.)

A from source build of lang/gcc5 reports the
need for such options.
Comment 4 Mark Millard 2017-08-11 22:46:45 UTC
(In reply to Mark Millard from comment #3)

You can use ldd on the a,out after each type
of link to see the different bindings.
Comment 5 Jan Beich freebsd_committer 2017-08-15 17:23:24 UTC
Can you confirm the issue doesn't affect lang/gcc6 and lang/gcc7? The default is going to change soon per bug 219275.

I can reproduce in a pristine jail with nothing but gcc5 installed. gcc49, gcc48, gcc47, gcc46 are also affected.

(In reply to Mark Millard from comment #3)
> The compile/link command did not specify: -Wl,-rpath=...

Maybe -Wl,-rpath should be added to the specfile instead of relying on ldconfig hints roulette. Not having sane defaults is a bug.

(In reply to Mark Millard from comment #3)
> mix of system and gcc libraries than gcc5

Tier1 and some Tier2 archs don't have system GCC anymore. It's enough to install more than one lang/gcc* to get ambiguity about libstdc++ et al.
Comment 6 Mark Millard 2017-08-15 19:09:45 UTC
(In reply to Jan Beich from comment #5)

>(In reply to Mark Millard from comment #3)
>> mix of system and gcc libraries than gcc5
>
>Tier1 and some Tier2 archs don't have system GCC anymore. It's enough to install more
>than one lang/gcc* to get ambiguity about libstdc++ et al.

There are still system libraries that are ambiguously
bound to when the system has no gcc of its own. Use
of:

-Wl,-rpath=/usr/local/lib/gcc<?>

for the appropriate <?> prevents that. For example:

       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
vs.
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)

But there is also the lack of:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

when -Wl,-rpath=/usr/local/lib/gcc<?> is used.

This can interact badly with binding to:

       libthr.so.3 => /lib/libthr.so.3 (0x8011d3000)

since libthr was built based on the context for:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

and not the implicit material in libstdc++. See
bugzilla 221423.

For reference:

g++6 -std=c++14 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc6 -O2
cpp_clocks_investigation.cpp

# ldd a.out
a.out:
       libstdc++.so.6 => /usr/local/lib/gcc6/libstdc++.so.6 (0x800844000)
       libm.so.5 => /lib/libm.so.5 (0x800bd9000)
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)
       libthr.so.3 => /lib/libthr.so.3 (0x80101d000)
       libc.so.7 => /lib/libc.so.7 (0x801245000)

and the result has crash problems from the
odd mix of libstdc++ supplying what would be
used from libcxxrt inlibthr. (FYI:
cpp_clocks_investigation.cpp is pure
standard C++ code.)

(I did not notice libthr using libgcc_s but if it
did then it is the same sort of problem as for
libstdc++ providing when the system libcxxrt
would provide.)

By contrast:

clang++ -std=c++14 -Wpedantic -Wall -pthread cpp_clocks_investigation.cpp 

# ldd a.out
a.out:
       libc++.so.1 => /usr/lib/libc++.so.1 (0x8008a6000)
       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)
       libm.so.5 => /lib/libm.so.5 (0x800d90000)
       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
       libthr.so.3 => /lib/libthr.so.3 (0x8011d3000)
       libc.so.7 => /lib/libc.so.7 (0x8013fb000)

works fine and libthr has libcxxrt to bind to (and
the system libgcc_s if libthr has any binding to
there).


Separately from the above:

-Wl,-rpath=/usr/local/lib/gcc<?>

also disambiguates when having multiple lang/gcc* 's
installed. But this type of context is not required
for there to be binding problems.
Comment 7 Mark Millard 2017-08-15 19:32:01 UTC
(In reply to Mark Millard from comment #6)

Dumb typo. Wrong:

See bugzilla 221423.

Should have been:

See bugzilla 221288 .
Comment 8 Mark Millard 2017-08-15 22:22:52 UTC
(In reply to Jan Beich from comment #5)

> Can you confirm the issue doesn't affect lang/gcc6 and lang/gcc7?
> The default is going to change soon per bug 219275.

I'm not sure which issue(s)/aspect(s) you are after,
so I pick the following to try to answer.

I strongly expect that an ldd on the original
context that was using std::locale(LocaleName)
would show something implying a mix of system
and gcc original definitions, where at run-time
a specific binding ends up being made. (But no
one has posted such ldd output for the failing
context(s).)

I expect that what is required is producing the
program and libraries it is bound to such that
that they avoid the mix and bind at run time to
the same implementation related materials as
they all were built with.

I expect that such applies to all lang/gcc*
examples, including gcc6 and gcc7 and the
older gcc5 (and before).

This hole area of bindings is a mess. Progressing
from gccN to gcc <N+1> is an example were if

-Wl,-rpath=/usr/local/lib/gccN

was used then it looks explicitly for files from:

/usr/local/lib/gccN/

and if lang/gccN is uninstalled they will not be
there to be found. It takes a rebuild or other
form of forced redirection to have it try looking
in:

/usr/local/lib/gcc<N+1>/

instead. Even if it looks and finds a binding in
the new place it can try to use, the behavior need
not be compatible once bound.

Some types of system have a means of leaving the
libraries around for binding even when the compiler
and such is no long around for the version in
question.

Without -Wl,-rpath=/usr/local/lib/gccN involved
there are other issues. But sometimes the binding
that results happens to work better than does with
-rpath in use (since other libraries involved
were not set up for the -rpath libraries but,
say, system ones).

I'm not sure there is a universal, fixed answer to
which binding is better for the likes of (gcc6
example):

       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
vs.
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)

but as things are the run-time binding is
controlled via use or not of the:

-Wl,-rpath=/usr/local/lib/gccN

Any set of libraries that is put to use in a program
but that ends up being originally based overall on a
mix of the two bindings (build time) is likely to end
up being a problem combination when one implementation
is actually bound.

However, as I understand it, that option does not
determine the use or not of the likes of:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

because a bunch of those bindings can instead be
found from the likes of:

       libstdc++.so.6 => /usr/local/lib/gcc6/libstdc++.so.6 (0x800844000)

if it is involved, even without a -rpath in the link.

Again a set of libraries used in a program but
that mix the original contexts is likely to
end up being a problem combination. (The
program needs to match as well.)

It appears that avoiding mixes is generally
(but not universally?) required (both for
libgcc_s alternative and for libcxxrt vs.
implicit in libstdc++ ).

In case an example makes it clearer:

For my libthr example: It appears to me that a program
using libstdc++ itself or in libraries would need a
libthr equivalent that had also been built based on
libstdc++ as libstdc++ is now constructed. Similarly
for any libgcc_s use by the libthr equivalent.

An alternate would be a libstdc++ that was built based
on the system libgcc_s and libcxxrt and so that libstdc++
did not provide various bindings to gcc specifics that
libstdc++ now does --and there would be no gcc based
libgcc_s in use. As I understand g++ and libstdc++ is
not designed for this sort of structure.
Comment 9 Mark Millard 2017-08-16 03:42:56 UTC
Here are lang/gcc7 and system clang compile/link results as viewed
by ldd (all under head -r322287 in a Virtual Box virtual machine):
things look good until I try my threading example. Then one
combination fails (the -rpath one!).

# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800824000)
	libm.so.5 => /lib/libm.so.5 (0x800bb8000)
	libgcc_s.so.1 => /usr/local/lib/gcc7/libgcc_s.so.1 (0x800de5000)
	libc.so.7 => /lib/libc.so.7 (0x800ffc000)

# ./a.out

Note: The above did not crash but had no output.

# g++7 -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800824000)
	libm.so.5 => /lib/libm.so.5 (0x800bb8000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800de5000)
	libc.so.7 => /lib/libc.so.7 (0x800ffb000)

# ./a.out

Note: The above did not crash but had no output.

# clang++ -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libc++.so.1 => /usr/lib/libc++.so.1 (0x800824000)
	libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800af0000)
	libm.so.5 => /lib/libm.so.5 (0x800d0e000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800f3b000)
	libc.so.7 => /lib/libc.so.7 (0x801151000)

# ./a.out

Note: The above did not crash but had no output.


Replacing the locale line with:

                std::locale l = std::locale("NOSUCH::en_US.UTF-8");
 
# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 locale_failure_test.cc

# ./a.out
locale::facet::_S_create_c_locale name not valid

# g++7 -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ./a.out
locale::facet::_S_create_c_locale name not valid

# ./a.out
collate_byname<char>::collate_byname failed to construct for NOSUCH::en_US.UTF-8

So no exception was thrown in any of the examples and the
code did not fail.


Trying instead:

# more exception_test.cc
#include <exception>

int main(void)
{
    try { throw std::exception(); }
    catch (std::exception& e) {}
    return 0;
}

# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 exception_test.cc

# ./a.out

# g++7 -std=c++14 -Wpedantic -Wall -O2 exception_test.cc

# ./a.out

# clang++ -std=c++14 -Wpedantic -Wall -O2 exception_test.cc

# ./a.out


So none of them fail.

But trying my standard-C++ program that uses C++ threads:

# g++7 -std=c++14 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc7 -O2 cpp_clocks_investigation.cpp

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800844000)
	libm.so.5 => /lib/libm.so.5 (0x800bd8000)
	libgcc_s.so.1 => /usr/local/lib/gcc7/libgcc_s.so.1 (0x800e05000)
	libthr.so.3 => /lib/libthr.so.3 (0x80101c000)
	libc.so.7 => /lib/libc.so.7 (0x801244000)

# ./a.out
. . . (omitted) . . .
Segmentation fault (core dumped)

# g++7 -std=c++14 -Wpedantic -Wall -pthread -O2 cpp_clocks_investigation.cpp# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800844000)
	libm.so.5 => /lib/libm.so.5 (0x800bd8000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800e05000)
	libthr.so.3 => /lib/libthr.so.3 (0x80101b000)
	libc.so.7 => /lib/libc.so.7 (0x801243000)

# ./a.out
. . . (omitted) . . .
End of clock tests.

So it worked for /lib/libgcc_s.so.1 but not for /usr/local/lib/gcc7/libgcc_s.so.1
and I must have been wrong about /lib/libcxxrt.so.1 being what mattered.

This threading example is a context where -Wl,-rpath=/usr/local/lib/gcc7
prevents correct operation because of cross library dependencies on
implementation details of the build-time context vs. the mismatched
runtime context for libthr.so.3 vs. libgcc_s.so.1 .


# clang++ -std=c++14 -Wpedantic -Wall -pthread -O2 cpp_clocks_investigation.cpp

# ldd a.out
a.out:
	libc++.so.1 => /usr/lib/libc++.so.1 (0x800844000)
	libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b10000)
	libm.so.5 => /lib/libm.so.5 (0x800d2e000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800f5b000)
	libthr.so.3 => /lib/libthr.so.3 (0x801171000)
	libc.so.7 => /lib/libc.so.7 (0x801399000)

# ./a.out
. . . (omitted) . . .
End of clock tests.

So this also worked. Again /lib/libthr.so.3 and /lib/libgcc_s.so.1
go together just fine.