Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jun 2013 01:55:08 +0200
From:      Michael Gmelin <freebsd@grem.de>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        "freebsd-ports@freebsd.org Ports" <freebsd-ports@freebsd.org>, Matthias Andree <mandree@FreeBSD.org>
Subject:   Re: Are ports supposed to build and run on 10-CURRENT?
Message-ID:  <20130626015508.426ab5b9@bsd64.grem.de>
In-Reply-To: <C1CC40FC-4489-4164-96B7-5E1A25DCB37F@FreeBSD.org>
References:  <20130613031535.4087d7f9@bsd64.grem.de> <EF830CD7-00F1-4628-8515-76133BBE85E7@FreeBSD.org> <C1CC40FC-4489-4164-96B7-5E1A25DCB37F@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 22 Jun 2013 00:27:53 +0200
Dimitry Andric <dim@FreeBSD.org> wrote:

> On Jun 21, 2013, at 22:07, Dimitry Andric <dim@freebsd.org> wrote:
> > On Jun 13, 2013, at 03:15, Michael Gmelin <freebsd@grem.de> wrote:
> > ...

Hi Dimitry,

Despite my patch to mitigate the problem I discussed and analyzed the
initialization order issue and I think there is a something wrong in
10-CURRENT.

The problem is that static initialization happens in the expected
order (same translation unit), but termination does *not* happen in the
reverse order of initialization, which - according to the C++ standard
section 3.6.3 should be guaranteed:

"If the completion of the constructor or dynamic initialization of an
object with static storage duration is sequenced before that of
another, the completion of the destructor of the second is sequenced
before the initiation of the destructor of the first."

The following conditions have to be met in order to show the problem:

1. Two static objects defined in the translation unit containing main
2. Definition of one of the underlying objects is in a separate
   source which is used to build a shared library
3. Both, the translation unit containing main an the one forming the
   shared library are compiled using -fPIC (or -fpic).

The problem happens on:
- 10-CURRENT with system clang
- 10-CURRENT with clang 3.3 from ports

It doesn't happen on:
- 10-CURRENT with system gcc
- 9.1-RELEASE with system gcc
- 9.1-RELEASE with system clang
- 9.1-RELEASE with clang 3.3 from ports

Also, it does *not* happen on:
- 9.1-RELEASE running executables built on 10-CURRENT (any compiler)

I stripped the problem down to an easy to handle test case, you can
find as an patch at the end of this mail or download a tarball at
http://blog.grem.de/majortom.tgz

To execute the test:

fetch -o - http://blog.grem.de/majortom.tgz | tar -xzf -
cd majortom
make run

The expected outcome is:

        Ground             | Outer::Outer
          Control          | Inner::Inner
            to             |    main()
              Major        | Inner::~Inner
                Tom        | Outer::~Outer


The actual outcome on 10-CURRENT system clang or clang33 from ports is:

        Ground             | Outer::Outer
          Control          | Inner::Inner
            to             |    main()
                Tom        | Outer::~Outer
              Major        | Inner::~Inner


Which is really bad (not just for Bowie).

Time to open another PR?

Cheers,
Michael

--- majortom.patch begins here ---
diff -x .git -ruN majortom.old/Makefile majortom/Makefile
--- majortom.old/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ majortom/Makefile	2013-06-25 22:40:48.039332456 +0000
@@ -0,0 +1,21 @@
+CXX?=c++
+
+all: example
+
+out.o: out.cpp out.h
+	$(CXX) -pthread -c -fPIC out.cpp -I. -I/usr/local/include -o out.o
+
+libout.so: out.o
+	$(CXX) -pthread -shared -fPIC out.o -o libout.so
+
+main.o: main.cpp out.h
+	$(CXX) -pthread -c -fPIC main.cpp -I. -I/usr/local/include -o main.o
+
+example: libout.so main.o
+	$(CXX) -pthread -fPIC -L. -lout main.o -o example
+
+run: example
+	@LD_LIBRARY_PATH=. ./example
+
+clean:
+	rm -f *.so example *.o *~
\ No newline at end of file
diff -x .git -ruN majortom.old/main.cpp majortom/main.cpp
--- majortom.old/main.cpp	1970-01-01 00:00:00.000000000 +0000
+++ majortom/main.cpp	2013-06-25 22:43:27.116055202 +0000
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <out.h>
+
+struct Inner
+{
+    Inner() {
+        printf("\t  Control          | Inner::Inner\n");
+    }
+
+    ~Inner() {
+        printf("\t      Major        | Inner::~Inner\n");
+    }
+};
+
+static Outer outerInstance;
+static Inner innerInstance;
+
+int main() {
+  printf("\t    to             |    main()\n");
+}
diff -x .git -ruN majortom.old/out.cpp majortom/out.cpp
--- majortom.old/out.cpp	1970-01-01 00:00:00.000000000 +0000
+++ majortom/out.cpp	2013-06-25 22:42:55.188061650 +0000
@@ -0,0 +1,10 @@
+#include <out.h>
+#include <stdio.h>
+
+Outer::Outer() {
+    printf("\tGround             | Outer::Outer\n");
+}
+
+Outer::~Outer() {
+    printf("\t        Tom        | Outer::~Outer\n");
+}
diff -x .git -ruN majortom.old/out.h majortom/out.h
--- majortom.old/out.h	1970-01-01 00:00:00.000000000 +0000
+++ majortom/out.h	2013-06-25 22:25:44.817345120 +0000
@@ -0,0 +1,11 @@
+#ifndef OUT_H
+#define OUT_H
+
+class Outer
+{
+public:
+    Outer();
+    ~Outer();
+};
+
+#endif
--- majortom.patch ends here ---

-- 
Michael Gmelin



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