Hi Bert,
sorry for the long delay in responding to this.
There must be some other code that calls setStopped, because if you look
at the main event processing loop in AmSession::run again (seems like I
did not look at it closely enough either):
-----------------
while (!sess_stopped.get() ||
(dlg.getStatus() == AmSipDialog::Disconnecting)// ||
// (dlg.getUACTransPending())
){
waitForEvent();
processEvents();
DBG("%s dlg.getUACTransPending() = %i\n",
dlg.callid.c_str(),dlg.getUACTransPending());
}
--------------
you will notice that it is *running* while sess_stopped = false (i.e.
before setStopped is called) OR dlg.getStatus == Disconnecting.
That means that the loop will continue to run after setStopped has been
called, until the state of the dialog is different from Disconnecting.
The reason for this is, that the session should run after a session that
has initialized but CANCELed, until the CANCEL did get some reply (and,
it should actually go into disconnecting state if BYE is sent out - but
that is another story).
So, check again AmSession.cpp for the places where setStopped is called,
that is by default
- AmAudioEvent::cleared
- AmSession::Exception in onSessionStart
- AmSession::Exception in onInvite
- AmSession::Exception in main loop
- BYE received (onBye)
- AmSystemEvent::ServerShutdown (onSystemEvent)
- RTP timeout (onRTPTimeout)
If your session is derived from B2B session (or AmB2ABSession), check
the other places in their respective implementations.
I would have been really surprised if a session would be destructed
before setStopped is called, because I use application sessions running
after dialog ended for a long time extensively (namely in DSM, using
dlg.bye from mod_dlg, and processing stuff well after that).
hth
Stefan
o Bert Fraterman [09/24/09 11:48]:
Hi Stefan,
Thanks for your reply, it clarifies a couple of things for me. To be a
100% sure, I ran another test yesterday and after a couple of thousand
test calls (with sipp), it detected an early destruction of the session.
The code was set up to wait for an external event (by some other thread)
for roughly 6 or 7 seconds after the BYE was sent. Every call to
setStopped() was paired with the setting of a volatile boolean, and in
the destructor this boolean was checked, resulting in an error if it was
not set. The call to setStopped() was made within the normal SEMS event
loop (by posting a custom SEMS event to the session, which signals the
session should be stopped).
As stated above, the destructor for the session gave a warning only
after a couple of minutes of testing.
I have looked at the AmSessionContainer::clean_sessions method, and I
can see it checks that the Thread is still running (with
AmThread::is_stopped()), but I can't find any relation to
AmSession::sess_stopped state. I'll elaborate (correct me if I'm wrong
here):
- Amthread puts the AmThread in _stopped(false) state and starts the
session. Once run() is done, it puts _stopped in true state.
void * AmThread::_start(void * _t)
{
AmThread* _this = (AmThread*)_t;
_this->_pid = (pid_t) _this->_td;
DBG("Thread %lu is starting.\n", (unsigned long int)
_this->_pid);
_this->_stopped.set(false);
_this->run();
DBG("Thread %lu is ending.\n", (unsigned long int)
_this->_pid);
_this->_stopped.set(true);
return NULL;
}
- Once the code exits from the 'main event loop'(see below) in
AmSession::run, there isn't any code in AmSession::run that checks for
AmSession:sess_stopped state.
while (!sess_stopped.get() ||
(dlg.getStatus() == AmSipDialog::Disconnecting
)
- So AmSession::run can finish, without checking for the sess_stopped
state. Therefore, the AmThread::_start method can put the thread into
_stopped(true) state.
- In AmSessionContainer::clean_sessions, a check is made on
AmThread::_stopped state.
if(cur_session->is_stopped() && cur_session->detached.get()) {
DBG("session %p has been
destroyed'\n",(void*)cur_session->_pid);
delete cur_session;
}
- But that only checks if AmThread has stopped, not if the AmSession has
stopped.
So basically, AmThread::stopped can be true, while
AmSession::sess_stopped is still false. I think this makes it possible
for a session to be destroyed before setStopped() is called.
I hope this clearly explains the situation and I haven't overlooked
anything. Do you think the above scenario is possible?
An extra in check in AmSessionContainer::clean_sessions on
AmSession::sess_stopped might solve the problem, but I'm not sure it
that affects any other code.
Kind regards,
Bert Fraterman
*From:* [email protected]
[mailto:[email protected]] *On Behalf Of *Bert Fraterman
*Sent:* maandag 21 september 2009 13:41
*To:* [email protected]
*Subject:* [Sems] Problem with early session destruction
Hello,
I have developed a SEMS application in C++, but I had problems with
too
early destroyed sessions:
First, the BYE is send, and my sessions wait for some event, which is
launched by a separate thread. After this event is launched, the
session
is stopped with the setStopped() method call.
Sometimes, the session was destroyed before I called the setStopped()
method, which made me delve into the SEMS code.
are you sure the session was really destroyed, i.e. it was deleted?
If you look at AmSessionContainer::clean_sessions, you will see that the
sessions that are still running (!is_stopped()) are not deleted, only
those where setStopped() has been called. in the debug log you should
see something like 'Session xyz is still running' periodically.
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems
--
Stefan Sayer
VoIP Services
[email protected]
www.iptego.com
IPTEGO GmbH
Wittenbergplatz 1
10789 Berlin
Germany
Amtsgericht Charlottenburg, HRB 101010
Geschaeftsfuehrer: Alexander Hoffmann
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems