Closed tomvierjahn closed 7 years ago
I'm afraid this is news to me.
Unfortunately I do not have a MacOS dev environment, so I'm a bit in the blind here.
Does this always happen, or is it intermittent? Do you have a back trace? Do you have an expectation in a global/static variable?
Let me try and summarise what we are doing:
open_gl_mock.hpp
#ifndef TESTS_SRC_OPEN_GL_MOCK_HPP_
#define TESTS_SRC_OPEN_GL_MOCK_HPP_
#include "trompeloeil.hpp"
#include "GL/glew.h"
class OpenGLMock {
public:
MAKE_MOCK1(glClear, void(GLbitfield));
};
extern OpenGLMock open_gl_mock;
#endif // TESTS_SRC_OPEN_GL_MOCK_HPP_
open_gl_mock.cpp
#include "open_gl_mock.hpp"
OpenGLMock open_gl_mock;
extern template struct trompeloeil::reporter<trompeloeil::specialized>;
extern "C" {
void glClear(GLbitfield mask) {
open_gl_mock.glClear(mask);
}
}
test_clear_pass.cpp
#include "GL/glew.h"
#include "phx/clear_pass.hpp"
#include "trompeloeil.hpp"
#include "catch/catch.hpp"
#include "open_gl_mock.hpp"
extern template struct trompeloeil::reporter<trompeloeil::specialized>;
SCENARIO("The clear pass clears the active color and depth buffers.",
"[phx][phx::ClearPass]") {
GIVEN("A clear pass") {
phx::ClearPass clearPass;
WHEN("We execute the clear pass.") {
THEN("The glClear is called properly") {
REQUIRE_CALL(open_gl_mock,
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
.TIMES(1);
clearPass.Execute();
}
}
}
#0 0x00007fffc50ccd42 in __pthread_kill ()
#1 0x00000001003007a0 in pthread_kill ()
#2 0x00007fffc5032420 in abort ()
#3 0x00007fffc3b8594a in abort_message ()
#4 0x00007fffc3baac17 in default_terminate_handler() ()
#5 0x00007fffc46ba713 in _objc_terminate() ()
#6 0x00007fffc3ba7d49 in std::__terminate(void (*)()) ()
#7 0x00007fffc3ba7dc3 in std::terminate() ()
#8 0x000000010000521f in __clang_call_terminate ()
#9 0x00000001000052fc in trompeloeil::expectations<void (unsigned int)>::~expectations() at /Users/tom/.conan/data/trompeloeil/v25/rollbear/stable/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/trompeloeil.hpp:3224
#10 0x0000000100005275 in trompeloeil::expectations<void (unsigned int)>::~expectations() at /Users/tom/.conan/data/trompeloeil/v25/rollbear/stable/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/trompeloeil.hpp:3221
#11 0x0000000100005255 in OpenGLMock::~OpenGLMock() at /Users/tom/rwth/code/project_phoenix/tests/src/open_gl_mock.hpp:31
#12 0x0000000100004c85 in OpenGLMock::~OpenGLMock() at /Users/tom/rwth/code/project_phoenix/tests/src/open_gl_mock.hpp:31
#13 0x00007fffc5033178 in __cxa_finalize_ranges ()
#14 0x00007fffc50334b2 in exit ()
#15 0x00007fffc4f9e23c in start ()
BTW how can I get v28 via conan?
OK, cool. I'm pretty sure I understand what the problem is; C++ and its static initialization order fiasco, or in this case destruction.
Trompeloeil has a static recursive mutex, which is seen in the exception thrown. Your open_gl_mock
is a global, which has the same problem. The init fiasco is avoided by constructing the mutex in a function call, but the order of destruction is still undefined between the mutex and the global mock object. In this case, the mutex was destroyed first. When the open_gl_mock
is destroyed, it tries to acquire the mutex.
I'll see if I can make this work with the nifty counter idiom (from the same FAQ.) This is likely to take a few days, though.
Do you think you can work around it until then? One possible (but ugly, I admit) solution is to allocate your global mock on the heap, and leak it. Better, but probably more work, is to not have the mock as a global.
I'll try this.
v28 on conan. Yes, probably.
https://bintray.com/trompeloeil/trompeloeil/trompeloeil%3Arollbear/v28%3Astable
I'm in their queue for inclusion in "conan-center," but they're pretty over worked, and I expect feedback with changes I need to make, so it's likely to take a while.
Leaking does the trick. Terrific … yet terrifically ugly :-)
RE v28: What a pity. I would like to avoid adding more remotes. Otherwise, we diminish the advantage of a package manager …
… would you mind if we provided it in our own third party channel? That remote has to be included anyway.
If you can try the latest version on branch develop
, I'd be happy to receive your feedback.
I was not able to reproduce your exact problem, but I wrote a small nonsense program that exposed the bug I'm convinced is behind this, and could solve it using the exact same implementation technique. Unless I've misunderstood the situation, this should solve your problem, but there is always the chance for a misunderstanding.
Regarding conan: Sure, go ahead and mirror in your own channel if you want to.
Does not work unfortunately.
Output:
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: recursive_mutex lock failed: Invalid argument
Stack Trace:
#0 0x00007fff9ba69d42 in __pthread_kill ()
#1 0x00000001004dc7a0 in pthread_kill ()
#2 0x00007fff9b9cf420 in abort ()
#3 0x00007fff9a52294a in abort_message ()
#4 0x00007fff9a547c17 in default_terminate_handler() ()
#5 0x00007fff9b057713 in _objc_terminate() ()
#6 0x00007fff9a544d49 in std::__terminate(void (*)()) ()
#7 0x00007fff9a544dc3 in std::terminate() ()
#8 0x0000000100405cdf in __clang_call_terminate ()
#9 0x0000000100409b2c in trompeloeil::expectations<unsigned int ()>::~expectations() at /Users/tom/Desktop/trompeloeil.hpp:3242
#10 0x0000000100409965 in trompeloeil::expectations<unsigned int ()>::~expectations() at /Users/tom/Desktop/trompeloeil.hpp:3239
#11 0x00000001004097e5 in OpenGLMockInternal::~OpenGLMockInternal() at /Users/tom/rwth/code/project_phoenix/tests/src/mocks/open_gl_mock.hpp:54
#12 0x0000000100404ab5 in OpenGLMockInternal::~OpenGLMockInternal() at /Users/tom/rwth/code/project_phoenix/tests/src/mocks/open_gl_mock.hpp:54
#13 0x00007fff9b9d0178 in __cxa_finalize_ranges ()
#14 0x00007fff9b9d04b2 in exit ()
#15 0x00007fff9b93b23c in start ()
But thank you very much for trying to fix it
Rats. I thought I had this one. Oh well, back to the drawing board. Thanks for the feedback.
Just gave it an extra try with an MWE:
test.cpp:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "trompeloeil.hpp"
namespace trompeloeil {
template <>
void reporter<specialized>::send(severity s, const char* file,
unsigned long line, const char* msg) {
std::ostringstream os;
if (line) os << file << ':' << line << '\n';
os << msg;
auto failure = os.str();
if (s == severity::fatal) {
FAIL(failure);
} else {
CAPTURE(failure);
CHECK(failure.empty());
}
}
} // namespace trompeloeil
mock.hpp:
#ifndef MOCK_HPP_
#define MOCK_HPP_
#include "trompeloeil.hpp"
class Mock {
public:
MAKE_MOCK0(foo, void());
};
extern Mock mock;
#endif // MOCK_HPP_
mock.cpp:
#include "mock.hpp"
extern template struct trompeloeil::reporter<trompeloeil::specialized>;
Mock mock;
main.cpp:
#include <iostream>
#include "catch.hpp"
#include "mock.hpp"
extern template struct trompeloeil::reporter<trompeloeil::specialized>;
TEST_CASE("Try it", "[mwe]") {
REQUIRE_CALL(mock, foo());
mock.foo();
CHECK(true == true);
}
So I might have made a mistake when trying to include the latest develop version in our larger project. I'll come back once we have changed that …
I can confirm this issue with latest master and V28 an Travis CI (Trusty) with all versions of clang (tested 3.8, 3.9, 4.0), while GCC (5, 6, 7) works. Compiling locally with GCC 7 and Clang 4.0 doesn't show the issue and works too.
Switching to latest develop fixed the issue for me.
Sorry for my silence. I've been failing miserably in reproducing this problem. I'll have to take your word for it that my fix on develop
is OK. Ill make a release shortly, unless you find a reason for me to work more on this.
No worries, Björn.
I cannot check it before Sep 25.
Am 16.09.2017 um 13:43 schrieb Björn Fahller notifications@github.com:
Sorry for my silence. I've been failing miserably in reproducing this problem. I'll have to take your word for it that my fix on develop is OK. Ill make a release shortly, unless you find a reason for me to work more on this.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
Fix included in release v29. Reopen if there are still problems.
Using
Tests crash with:
in
trompeloeil.hpp
line 3224:Have you seen this before?