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