#486 Pure Virtual Function Call in OpalMixerNode::GetConferenceState

Development_Branch
closed-fixed
nobody
None
5
2014-04-01
2013-10-01
No

Stack trace:
msvcr110d.dll!_NMSG_WRITE(int rterrnum=25) Line 226 C
msvcr110d.dll!_purecall() Line 54 C

opald.dll!OpalMixerNode::GetConferenceState(OpalConferenceState & state={...}) Line 1425 C++
opald.dll!OpalMixerEndPoint::GetConferenceStates(std::list<OpalConferenceState,std::allocator<OpalConferenceState> > & states={...}, const PString & name={...}) Line 876 C++
opald.dll!SIPEndPoint::OnConferenceStatusChanged(OpalEndPoint & endpoint={...}, const PString & uri={...}, OpalConferenceState::ChangeType change=UserAdded) Line 442 C++
opald.dll!OpalManager::OnConferenceStatusChanged(OpalEndPoint & endpoint={...}, const PString & uri={...}, OpalConferenceState::ChangeType change=UserAdded) Line 1335 C++
opald.dll!OpalMixerEndPoint::OnNodeStatusChanged(const OpalMixerNode & node={...}, OpalConferenceState::ChangeType change=UserAdded) Line 959 C++
opald.dll!OpalMixerNode::AttachConnection(OpalConnection * connection=0x02b78fd0) Line 1287 C++
opald.dll!OpalMixerConnection::OpalMixerConnection(PSafePtr<OpalMixerNode,PSafePtrBase> node={...}, OpalCall & call={...}, OpalMixerEndPoint & ep={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 976 C++
mcu.dll!RcRoomConnection::RcRoomConnection(PSafePtr<OpalMixerNode,PSafePtrBase> node={...}, OpalCall & call={...}, RcRoomsManager & ep={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 9 C++
mcu.dll!RcRoomsManager::CreateConnection(PSafePtr<OpalMixerNode,PSafePtrBase> node={...}, OpalCall & call={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 30 C++
opald.dll!OpalMixerEndPoint::MakeConnection(OpalCall & call={...}, const PString & party={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 853 C++
opald.dll!OpalManager::MakeConnection(OpalCall & call={...}, const PString & remoteParty={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 723 C++
opald.dll!OpalManager::SetUpCall(const PString & partyA={...}, const PString & partyB={...}, void * userData=0x02d4f428, unsigned int options=0, OpalConnection::StringOptions * stringOptions=0x02d4f454) Line 553 C++

Discussion

  • Valeriy V. Argunov

    Debugger shows the error on line

    if (other != NULL && other->IsNetworkConnection()) {

    but it seems like the issue is not here.

    I'll try to find the reason.

     
    Last edit: Valeriy V. Argunov 2013-10-01
  • Valeriy V. Argunov

    The error occurs when I have a mixer node and add 2 calls in it (call 1 and call 2).
    While call 1 is setting up (SetUpCall thread, AsynchCallSetUp->...->OpalManager::OnIncomingConnection->...->SIPConnection::SIPConnection), mixer node tries to enumerate connections in OpalMixerNode::GetConferenceState for the call 2 (see call stack).

    Local connection of the call 1 is ready, but SIP connection for the call 1 is not constructed yet.

    OpalMixerNode::GetConferenceState, line

    PSafePtr<OpalConnection> other = conn->GetOtherPartyConnection();

    gets not fully constructed SIP connection and line

    if (other != NULL && other->IsNetworkConnection()) {

    tries to call IsNetworkConnection for the invalid connection object.

     
  • Valeriy V. Argunov

    So now it's possible to get an access to the OpalCall while it's connections are in the process of construction.
    So it's possible to enumerate/get invalid connections.

     
  • Robert Jongbloed

    • status: open --> open-fixed
     
  • Robert Jongbloed

    Checked in a possible fix.

     
  • Valeriy V. Argunov

    That patch doesn't fix the issue, I still get a "Pure Virtual Function Call" error.

    Remote connection is already in the OpalCall, and OpalMixerNode::GetConferenceState gets a simple PSafeReference pointer to the connection.
    I think the solution is not to add connection to the OpalCall in the base OpalConnection class c-tor (because at this time anybody who has OpalCall reference can get a reference to the invalid connection).
    It would be great to add OpalConnection to the call after the class (including derived classes) is constructed I think.

     
  • Robert Jongbloed

    • status: open-fixed --> open
     
  • Robert Jongbloed

    • status: open --> closed-fixed
     
  • Robert Jongbloed

    Your patch is the correct, and only, fix for the problem.

    The issue is quite fundamental to C++ and really difficult to work around. Moving the assignment to later constructors does not work as it only defers the problem. At every level someone could create a derived class with a different virtual function override, and the race condition is created again. The only solution is, as you have done, make sure the objects are locked and cannot be multiply accessed during construction.

     
  • Valeriy V. Argunov

    I see that OpalConnection must be added to the OpalEndpoint too, and this is done outside of the OpalConnection c-tor, so we don't have the same issue again.
    I think the right solution is to resolve this issue by the same way.

     
    Last edit: Valeriy V. Argunov 2014-04-01

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks