Skip to content

Commit

Permalink
Fix bogus timer ref counter during expire update.
Browse files Browse the repository at this point in the history
Many thanks to Trevor Francis for reporting and helping with troubleshooting and testing.

(cherry picked from commit 047b1b3)
  • Loading branch information
bogdan-iancu committed May 19, 2016
1 parent dea3a12 commit 21ad02f
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
16 changes: 13 additions & 3 deletions modules/dialog/dialog.c
Expand Up @@ -1741,10 +1741,20 @@ int pv_set_dlg_timeout(struct sip_msg *msg, pv_param_t *param,
if (dialog_replicate_cluster)
replicate_dialog_updated(dlg);

if (timer_update && update_dlg_timer(&dlg->tl, timeout) < 0) {
LM_ERR("failed to update timer\n");
return -1;
if (timer_update) {
switch ( update_dlg_timer(&dlg->tl, timeout) ) {
case -1:
LM_ERR("failed to update timer\n");
return -1;
case 1:
/* dlg inserted in timer list with new expire (reference it)*/
ref_dlg(dlg,1);
case 0:
/* timeout value was updated */
break;
}
}

} else if (current_processing_ctx) {
/* store it until we match the dialog */
ctx_timeout_set( timeout );
Expand Down
10 changes: 9 additions & 1 deletion modules/dialog/dlg_handlers.c
Expand Up @@ -1612,8 +1612,16 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)

/* update timer during sequential request? */
if (dlg->lifetime_dirty) {
if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1)
switch ( update_dlg_timer( &dlg->tl, dlg->lifetime ) ) {
case -1:
LM_ERR("failed to update dialog lifetime\n");
case 0:
/* timeout value was updated */
break;
case 1:
/* dlg inserted in timer list with new expire (reference it)*/
ref_dlg(dlg,1);
}
}
LM_DBG("dialog_timeout: %d\n", dlg->lifetime);
if ( event!=DLG_EVENT_REQACK ) {
Expand Down
14 changes: 12 additions & 2 deletions modules/dialog/dlg_replication.c
Expand Up @@ -344,12 +344,22 @@ int dlg_replicated_update(void)
bin_skip_int(2);

timeout -= time(0);
LM_DBG("Received updated timeout of %d for dialog %.*s\n", timeout, call_id.len, call_id.s);
LM_DBG("Received updated timeout of %d for dialog %.*s\n",
timeout, call_id.len, call_id.s);

if (dlg->lifetime != timeout) {
dlg->lifetime = timeout;
if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1)
switch (update_dlg_timer(&dlg->tl, dlg->lifetime) ) {
case -1:
LM_ERR("failed to update dialog lifetime!\n");
/* continue */
case 0:
/* timeout value was updated */
break;
case 1:
/* dlg inserted in timer list with new expire (reference it)*/
ref_dlg(dlg,1);
}
}

unref_dlg_unsafe(dlg, 1, d_entry);
Expand Down
7 changes: 6 additions & 1 deletion modules/dialog/dlg_timer.c
Expand Up @@ -426,6 +426,8 @@ static inline void detach_ping_node_unsafe(struct dlg_ping_list *it,int reinvite
-1 - failure (dialog is expired, so it cannot be added again) */
int update_dlg_timer( struct dlg_tl *tl, int timeout )
{
int ret;

lock_get( d_timer->lock);

if ( tl->next == FAKE_DIALOG_TL ) {
Expand All @@ -440,13 +442,16 @@ int update_dlg_timer( struct dlg_tl *tl, int timeout )
return -1;
}
remove_dlg_timer_unsafe(tl);
ret = 0;
} else {
ret = 1;
}

tl->timeout = get_ticks()+timeout;
insert_dlg_timer_unsafe( tl );

lock_release( d_timer->lock);
return 0;
return ret;
}

static inline struct dlg_tl* get_expired_dlgs(unsigned int time)
Expand Down

0 comments on commit 21ad02f

Please sign in to comment.