diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2009-12-29 23:05:45 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2009-12-29 23:05:45 +0000 |
commit | 5d2b47ffb829d1a1b443f0d446233ce92a7b9227 (patch) | |
tree | 9b9e8d672e698c815741c1c5cf6a8d64a40b1dcb /channels | |
parent | 28d16a3cb1e35fe7f65ec97eae3a9bd3f337955c (diff) |
Shut down the SIP session timers more gracefully, in order to prevent a possible crash.
(closes issue #16452)
Reported by: corruptor
Patches:
20091221__issue16452.diff.txt uploaded by tilghman (license 14)
Tested by: corruptor
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@236802 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 396db2350..af323d49e 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1668,6 +1668,7 @@ struct sip_st_dlg { int st_cached_max_se; /*!< Session-Timers cached Session-Expires */ enum st_mode st_cached_mode; /*!< Session-Timers cached M.O. */ enum st_refresher st_cached_ref; /*!< Session-Timers cached refresher */ + unsigned char quit_flag:1; /*!< Stop trying to lock; just quit */ }; @@ -5797,6 +5798,11 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) { struct sip_request *req; + if (p->stimer) { + ast_free(p->stimer); + p->stimer = NULL; + } + if (sip_debug_test_pvt(p)) ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); @@ -5872,6 +5878,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist) /* Destroy Session-Timers if allocated */ if (p->stimer) { + p->stimer->quit_flag = 1; if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) { AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, dialog_unref(p, "removing session timer ref")); @@ -23689,25 +23696,34 @@ static int proc_session_timer(const void *vp) } else { p->stimer->st_expirys++; if (p->stimer->st_expirys >= 2) { + if (p->stimer->quit_flag) { + goto return_unref; + } ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid); - + sip_pvt_lock(p); while (p->owner && ast_channel_trylock(p->owner)) { sip_pvt_unlock(p); usleep(1); + if (p->stimer && p->stimer->quit_flag) { + goto return_unref; + } sip_pvt_lock(p); } ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); ast_channel_unlock(p->owner); + sip_pvt_unlock(p); } } return_unref: if (!res) { /* An error occurred. Stop session timer processing */ - p->stimer->st_schedid = -1; - stop_session_timer(p); - + if (p->stimer) { + p->stimer->st_schedid = -1; + stop_session_timer(p); + } + /* If we are not asking to be rescheduled, then we need to release our * reference to the dialog. */ dialog_unref(p, "removing session timer ref"); |