access violation inside ADODB recordset Close












1















Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.



The problem was that we had a memory leak in our code:



void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}


This function is called often so a basic memory leak.
Fixed it with a unique pointer



void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}


Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.



inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}



Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.




So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.



After debugging it turns out that getDetailConfig is called from two different threads.



Thread1



void updateIconStatus()
{
getDetailConfig();
}


thread1



Thread ID 5bA8



Thread2



void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}


thread2



Thread ID 6A4C



So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.



Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?










share|improve this question























  • 0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

    – Hans Passant
    Nov 23 '18 at 14:20











  • Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

    – Hans Passant
    Nov 23 '18 at 14:22











  • I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

    – axalis
    Nov 23 '18 at 14:23


















1















Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.



The problem was that we had a memory leak in our code:



void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}


This function is called often so a basic memory leak.
Fixed it with a unique pointer



void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}


Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.



inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}



Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.




So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.



After debugging it turns out that getDetailConfig is called from two different threads.



Thread1



void updateIconStatus()
{
getDetailConfig();
}


thread1



Thread ID 5bA8



Thread2



void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}


thread2



Thread ID 6A4C



So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.



Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?










share|improve this question























  • 0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

    – Hans Passant
    Nov 23 '18 at 14:20











  • Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

    – Hans Passant
    Nov 23 '18 at 14:22











  • I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

    – axalis
    Nov 23 '18 at 14:23
















1












1








1








Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.



The problem was that we had a memory leak in our code:



void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}


This function is called often so a basic memory leak.
Fixed it with a unique pointer



void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}


Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.



inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}



Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.




So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.



After debugging it turns out that getDetailConfig is called from two different threads.



Thread1



void updateIconStatus()
{
getDetailConfig();
}


thread1



Thread ID 5bA8



Thread2



void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}


thread2



Thread ID 6A4C



So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.



Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?










share|improve this question














Still trying to figure out what is happening with ADODB's connections and why a certain crash is occuring.



The problem was that we had a memory leak in our code:



void getDetailConfig()
{
m_displayConf = new TestDetailDisplayCfg();
}


This function is called often so a basic memory leak.
Fixed it with a unique pointer



void getDetailConfig()
{
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}


Yay party, but now an acces violation started to happen inside ADODB's Recordset15::Close.



inline HRESULT Recordset15::Close ( ) {
HRESULT _hr = raw_Close();
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
}



Unhandled exception at 0x679E653F (msado15.dll) in LaneControl.exe:
0xC000041D: An unhandled exception was encountered during a user
callback.




So calling all destructors the right way caused a new issue, there are recordset's opened and closed somewhere.



After debugging it turns out that getDetailConfig is called from two different threads.



Thread1



void updateIconStatus()
{
getDetailConfig();
}


thread1



Thread ID 5bA8



Thread2



void CVTSDetailDisplay::setCurrentTestIconStatus(int status)
{
m_CurrentDialog->getDetailConfig();
}


thread2



Thread ID 6A4C



So these 2 threads call getDetailConfig where a recordset is closed which was opened on another thread and COM objects are Released and what not.



Is that a problem that you can't close ADO recordsets on another thread? Is it more a race condition?
What is going wrong here at ADODB's level?







c++ com ado






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 13:47









Serve LaurijssenServe Laurijssen

5,54032353




5,54032353













  • 0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

    – Hans Passant
    Nov 23 '18 at 14:20











  • Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

    – Hans Passant
    Nov 23 '18 at 14:22











  • I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

    – axalis
    Nov 23 '18 at 14:23





















  • 0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

    – Hans Passant
    Nov 23 '18 at 14:20











  • Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

    – Hans Passant
    Nov 23 '18 at 14:22











  • I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

    – axalis
    Nov 23 '18 at 14:23



















0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

– Hans Passant
Nov 23 '18 at 14:20





0xC000041D does not actually have that much to do with ADODB. It can occur in a 32-bit app that runs on a 64-bit version of Windows. There was another exception before this one that got thrown in a windows message handler (aka WndProc, aka "user callback"). Such an exception is quite difficult to handle correctly since the callback started in the 64-bit window manager and it can't unwind the stack properly through these layers. Focus on seeing that first mishap, that's where it started to fall apart. Force the debugger to stop on the "first chance exception"

– Hans Passant
Nov 23 '18 at 14:20













Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

– Hans Passant
Nov 23 '18 at 14:22





Fwiw, ADODB is not thread-safe. You have to marshal the interface pointer, typically most easily done this way.

– Hans Passant
Nov 23 '18 at 14:22













I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

– axalis
Nov 23 '18 at 14:23







I would basically think that the object has been tried to be released twice (for the reason described in my answer), AKA "double-delete", so the second release indeed failed as the object was already no longer valid. And indeed, possible non-thread-safety of ADODB (which I don't know much about) can only add another injury to that.

– axalis
Nov 23 '18 at 14:23














1 Answer
1






active

oldest

votes


















1














I'd think it is a race condition.



If the getDetailConfig() function was already called before, and then both threads call the getDetailConfig(), this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr is not inherently thread-safe AFAIK).



You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex; as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf member) and then adding



void getDetailConfig()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_displayConf = std::make_unique<TestDetailDisplayCfg>();
}


to make sure the exchange is locked between threads.






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53447900%2faccess-violation-inside-adodb-recordset-close%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    I'd think it is a race condition.



    If the getDetailConfig() function was already called before, and then both threads call the getDetailConfig(), this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr is not inherently thread-safe AFAIK).



    You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex; as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf member) and then adding



    void getDetailConfig()
    {
    std::unique_lock<std::mutex> lock(m_mutex);
    m_displayConf = std::make_unique<TestDetailDisplayCfg>();
    }


    to make sure the exchange is locked between threads.






    share|improve this answer






























      1














      I'd think it is a race condition.



      If the getDetailConfig() function was already called before, and then both threads call the getDetailConfig(), this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr is not inherently thread-safe AFAIK).



      You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex; as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf member) and then adding



      void getDetailConfig()
      {
      std::unique_lock<std::mutex> lock(m_mutex);
      m_displayConf = std::make_unique<TestDetailDisplayCfg>();
      }


      to make sure the exchange is locked between threads.






      share|improve this answer




























        1












        1








        1







        I'd think it is a race condition.



        If the getDetailConfig() function was already called before, and then both threads call the getDetailConfig(), this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr is not inherently thread-safe AFAIK).



        You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex; as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf member) and then adding



        void getDetailConfig()
        {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_displayConf = std::make_unique<TestDetailDisplayCfg>();
        }


        to make sure the exchange is locked between threads.






        share|improve this answer















        I'd think it is a race condition.



        If the getDetailConfig() function was already called before, and then both threads call the getDetailConfig(), this can result in both threads calling the destructor (of the object which was there before) simultaneously (std::unique_ptr is not inherently thread-safe AFAIK).



        You'd then need to ensure critical section for the exchange of the pointers, for example adding std::mutex m_mutex; as a member of your class (ideally to the first place in the members list so it remains valid longer than the m_displayConf member) and then adding



        void getDetailConfig()
        {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_displayConf = std::make_unique<TestDetailDisplayCfg>();
        }


        to make sure the exchange is locked between threads.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 23 '18 at 14:15

























        answered Nov 23 '18 at 14:10









        axalisaxalis

        4,7101013




        4,7101013






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53447900%2faccess-violation-inside-adodb-recordset-close%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Berounka

            Sphinx de Gizeh

            Different font size/position of beamer's navigation symbols template's content depending on regular/plain...