none
Crash when performing mutithreaded unit test with thread local variables RRS feed

  • Question

  • Hello, I have posted this question before to the Visual Studio testing forum. There I got the suggestion to post my question again here:

    I try to write unit tests for my Visual C++ native static library. I'm using VC++ 2017. My development PC runs with Windows 10.

    The tests fail, when I create additional threads in my test and use complex thread_local variables, like in this example:

    In my lib:

        #include <unordered_map>
        #include<string>
    
        class TlsObject
        {
        public:
            static void clear_map() {
                mymap.clear();
            }
    
        private:
            thread_local static std::unordered_map<std::string, std::string> mymap;
        };
    
        ...
    
        thread_local std::unordered_map<std::string, std::string> TlsObject::mymap;

    Here is the unit test code:

        #include "stdafx.h"
        #include "CppUnitTest.h"
        #include "../TLSUnittest/TlsObject.h"
        #include <future>
        #include <string>
        #include <unordered_map>
    
        using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    
        namespace SomeUnittest
        {       
            TEST_CLASS(UnitTest1)
            {
            public:
                TEST_METHOD(TestMethod1) {
                    TlsObject::clear_map(); // works fine here!!
                    auto future = std::async(std::launch::async, []() { 
                        TlsObject::clear_map(); // throws exception here!!
                        return 0; });
                    future.wait();
                }
    
            };
        }

    It seems as if the constructor of the std::unordered_map was not called before entering the lamda code. Therefore my code produces a segmentation fault. This finally causes the unit test to fail.

    The same code as in the unit test works fine when I link it to a console .exe.

    What could be the reason for the unit test failing, while the .exe has no problem?

    Tuesday, October 10, 2017 8:06 AM

Answers

  • Try a different approach:

    private:

       static std::unordered_map<std::string, std::string> & mymap()

       {

          thread_local static std::unordered_map<std::string, std::string> m;

          return m;

       }

    Needs some derived adjustments.

    The UnitTest is a DLL, which probably has specific initialisation characteristics.

    Tuesday, October 10, 2017 5:58 PM

All replies

  • I try to write unit tests for my Visual C++ native static library. I'm using VC++ 2017. My development PC runs with Windows 10.

    The tests fail, when I create additional threads in my test and use complex thread_local variables, like in this example:

    In my lib:

        #include <unordered_map>
        #include<string>
    
        class TlsObject
        {
        public:
            static void clear_map() {
                mymap.clear();
            }
    
        private:
            thread_local static std::unordered_map<std::string, std::string> mymap;
        };
    
        ...
    
        thread_local std::unordered_map<std::string, std::string> TlsObject::mymap;

    Here is the unit test code:

        #include "stdafx.h"
        #include "CppUnitTest.h"
        #include "../TLSUnittest/TlsObject.h"
        #include <future>
        #include <string>
        #include <unordered_map>
    
        using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    
        namespace SomeUnittest
        {       
            TEST_CLASS(UnitTest1)
            {
            public:
                TEST_METHOD(TestMethod1) {
                    TlsObject::clear_map(); // works fine here!!
                    auto future = std::async(std::launch::async, []() { 
                        TlsObject::clear_map(); // throws exception here!!
                        return 0; });
                    future.wait();
                }
    
            };
        }

    It seems as if the constructor of the std::unordered_map was not called before entering the lamda code. Therefore my code produces a segmentation fault. This finally causes the unit test to fail.

    The same code as in the unit test works fine when I link it to a console .exe.

    What could be the reason for the unit test failing, while the .exe has no problem?

    Friday, October 6, 2017 1:37 PM
  • Hi Alexander,

    Thank you posting in MSDN forum.

    >> The tests fail, when I create additional threads in my test and use complex thread_local variables

    What error message did you get? Please share it that could help us to analyze your issue better.

    How about test in Visual Studio 2015? If it works fine in Visual Studio 2015, it seems that caused by Visual Studio 2017. If it also failed in Visual Studio 2015, I doubt that caused by some problem of the static library.

    Please have a look at following thread might helpful for you:

    https://stackoverflow.com/questions/36199598/visual-studio-unit-testing-a-static-library-prevents-additional-dependencies-in

    https://stackoverflow.com/questions/37174750/unit-testing-c-static-library

    Hope it helps.

     

    Regards,

    Fletcher


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Fletch Zhou Monday, October 9, 2017 4:08 AM
    Monday, October 9, 2017 4:08 AM
  • I just tested the same code with VS 2015. The same problem occurs. It looks a bit diefferent, because the test runner actually crashes. (If you want, I could provide you the Code as VS 2015 Project)

    I did further tests, which seem to prove that the memory for thread locals is provided, but the initializers are not executed, when (like in the unit test environment) the code is executed in a dynamically loaded .dll. According to the article: 

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms682594(v=vs.85).aspx 

    According to this article, the problem should be solved since Windows Vista. To me it seems, the problem might not be solved completely. Since it seems to allocate the memory correctly, but the initialization is not executed.

    For me it is important to know, whether the allocation is done correctly. As long as I accept a memory leak in case of dynamically loaded libraries, I can work around the problem as long as I can be sure, the allocation is done correctly.

    Regards

    Alexander




    Monday, October 9, 2017 1:19 PM
  • Hi Alexander,

    Thanks for your response. 

    Change the code

    thread_local std::unordered_map<std::string, std::string> TlsObject::mymap;


    to

    thread_local static std::unordered_map<std::string, std::string> TlsObject::mymap;

    and see.

    Btw, this issue seems related to thread local variables in C++, to be honest I am not an expert of C++, I suggest you post the issue in C++ forum, the experts there might provide a more professional explanation of it.

    Your understanding and cooperation will be much appreciated.

     

    Best regards,

    Fletcher           


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Fletch Zhou Tuesday, October 10, 2017 7:00 AM
    Tuesday, October 10, 2017 7:00 AM
  • Hi Fletcher,

    The variable is already declared static in the class. declaring it static again in the .cpp file, where the variable is initialized, would just cause a compiler error:

    Error C2720 'TlsObject::mymap': 'thread_local static ' storage-class specifier illegal on members TlsLib e:\syncplicity\z000esgf\documents\visual studio 2015\projects\tlsbug\tlslib\tlsobject.cpp 3

    I posted my question again under a C++ forum. Here is the link.

    https://social.msdn.microsoft.com/Forums/en-US/b1c1f0a6-6bdf-4edd-9a57-ccfd6d0de29f/crash-when-performing-mutithreaded-unit-test-with-thread-local-variables?forum=parallelcppnative

    regards

      Alexander


    Tuesday, October 10, 2017 7:42 AM
  • Here is the link to the original post:

    https://social.msdn.microsoft.com/Forums/en-US/457e8279-f744-4354-9992-86d3bf7adcec/why-does-my-native-c-unit-test-in-visualstudio-2017-crash-when-using-multiple-threads-with-complex?forum=vsunittest

    Tuesday, October 10, 2017 8:29 AM
  • Hi Alexander,

    Thanks for your feedback.

    I found this article  which mentioned some limitations of thread local variables, maybe it could give you some hints.

    As I'm not a moderator at this forum, I still cannot move the thread by my account. And I saw you've posted a new thread there, really hope you'll get a better support there.

    Thank you so much for your understanding.

      

    Best regards,

    Fletcher


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Fletch Zhou Tuesday, October 10, 2017 9:15 AM
    Tuesday, October 10, 2017 9:15 AM
  • Try a different approach:

    private:

       static std::unordered_map<std::string, std::string> & mymap()

       {

          thread_local static std::unordered_map<std::string, std::string> m;

          return m;

       }

    Needs some derived adjustments.

    The UnitTest is a DLL, which probably has specific initialisation characteristics.

    Tuesday, October 10, 2017 5:58 PM
  • Thanks a lot! I have tested with this slightly different implementation and it works just fine!
    Wednesday, October 11, 2017 9:36 AM