Hello,
o Bert Fraterman [02/06/09 11:08]:
Another problem in the category 'closing down sessions properly':
What if I want to wait an amount of time between the bye() and the
setStopped() calls? Like so:
this->dlg.bye();
... Code that takes considerable amount of time to run, a 200 OK
reply could be received in the mean time ...
this->setStopped();
As far as I can tell from the debug traces, SEMS tries to destroy the
session when the 200 OK reply is received. If the session is not stopped
at that moment with setStopped(), the AmSession::destroy() method will
not run.
I doubt your analysis. there must have been something else going on. if
you look at AmSession::run() this is what it does:
while (!sess_stopped.get() ||
(dlg.getStatus() == AmSipDialog::Disconnecting)){
waitForEvent();
processEvents();
DBG("%s dlg.getUACTransPending() = %i\n",
dlg.callid.c_str(),dlg.getUACTransPending());
}
... send bye if not done and another processEvents() loop until status
== Disconnected ..
onBeforeDestroy()
destroy()
Calling setStopped() after the 200 OK reply is received, results in the
session not being destroyed (and therefore not cleaned).
why? probably the reason is somewhere else (what is the dialog state?).
Another method you could try is the following:
Index: AmSipDialog.cpp
===================================================================
--- AmSipDialog.cpp (revision 1212)
+++ AmSipDialog.cpp (working copy)
@@ -365,7 +365,7 @@
switch(status){
case Disconnecting:
case Connected:
- status = Disconnected;
+ status = Disconnecting;
return sendRequest("BYE");
case Pending:
status = Disconnecting;
then the session's 'main loop' will run until a FR is received for the
BYE. maybe that is cleaner, but I think there was a reason why the
dialog was considered stopped immediately when sending BYE, which I
don't remember now.
As workaround, I call AmSession::destroy() manually when I call
setStopped(), so the session is always destroyed, but in all cases (even
when the 200 reply has been received), the internal logic will try to
destroy the session twice, resulting in warning messages that the
session could not be found. Not the prettiest solution, but the session
is destroyed and cleaned.
Is it a bug that the session isn't destroyed when setStopped() is called
after the 200 reply has been received?
Am I allowed in SEMS logic to have code in between the bye() and
setStopped() calls (the voicemail module has it too, but apparently it's
yes
quick enough to finish before the 200 reply is received?)?
no, it does not matter whether it takes much or little time to send the
email, or do any processing at that stage.
Look, there is one thread per session processing the signalling. only at
the end of AmSession::run, the session adds itself in the list of the to
be destroyed sessions, by calling AmSessionContainer::destroySession()
in destroy(). the AmSessionContainer goes periodically through this
list, and deletes all session, for which it's signalling thread is
really stopped.
So you are free to keep that thread running, even after you have called
destroy() it should not do any harm (you will only see that the session
container has that session in his to-be-deleted list). the cleaner way
is obviously to use the main loop as intended.
Regards
Stefan
Thanks,
Bert
-----Original Message-----
From: Stefan Sayer [mailto:[email protected]]
Sent: woensdag 4 februari 2009 21:31
To: Bert Fraterman
Cc: [email protected]
Subject: Re: [Sems] AmSipDispatcher 'could not dispatch reply' error
Hello,
o Bert Fraterman [02/04/09 17:55]:
I'm making a SEMS module in C++, and when I sent my bye, I also
immediately stop the session:
this->dlg.bye();
this->setStopped();
This pattern is also used in other modules, like the voicemail.
Unfortunately, when the SIP message 200 OK is received from the
client,
the AmSipDispatcher gives an error:
ERROR: [42074940] handleSipMsg (AmSipDispatcher.cpp:48): could
not dispatch reply: (Incoming 200 OK reply)
I suspect the AmSipDispatcher is trying to post an event to the
already
stopped session. Clearly, I'm not
interested in this event, otherwise I would've waited for it.
Also, this is not a critical error (I believe the internal state
machine
closes down the call properly), so I
would suggest to demote the error to a warning, or even to a debug
message (since it could be a very deliberate
choice not to wait for the event).
set unhandled_reply_loglevel in sems.conf (see sems.conf.sample):
# optional parameter:
unhandled_reply_loglevel={error|warn|info|debug|no}
#
# the default application logic implemented in the applications is to
stop
# the session right after sending BYE, without waiting for a reply. this
# leads to many log entries of the form
# ERROR: [b6fa6bb0] handleSipMsg (AmSipDispatcher.cpp:48): unhandled
# reply: [code:200;phrase:[OK];... ]
#
# This parameter sets the log lovel of unhandled positive (200 class)
replies.
#
# default: error
#
# unhandled_reply_loglevel=info
Is my statement correct, or am I closing down my session in the wrong
way?
Well, I do it the same way, and have not run into problems, even though
there is at least one case when it this is not correct: If BYE needs to
be authenticated. but it would be nice to modify the default processing
to wait until BYE is replied with FR or times out (is it on the tracker
already?).
Regards
Stefan
Thanks,
Bert
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems
--
Stefan Sayer
VoIP Services
[email protected]
www.iptego.com
IPTEGO GmbH
Am Borsigturm 40
13507 Berlin
Germany
Amtsgericht Charlottenburg, HRB 101010
Geschaeftsfuehrer: Alexander Hoffmann
_______________________________________________
Sems mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/sems