Răsfoiți Sursa

dialog: force cleanup of aged terminated dialogs

- reported by Dmitri Savolainen, GH #545
Daniel-Constantin Mierla 9 ani în urmă
părinte
comite
23a3481302

+ 4 - 0
modules/dialog/dlg_db_handler.c

@@ -425,6 +425,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
 				srjson_DestroyDoc(&jdoc);
 			}
 			dlg->iflags = (unsigned int)VAL_INT(values+22);
+			if(dlg->state==DLG_STATE_DELETED) {
+				/* end_ts used for force clean up not stored - set it to now */
+				dlg->end_ts = (unsigned int)time(0);
+			}
 			/*restore the timer values */
 			if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) {
 				LM_CRIT("Unable to insert dlg %p [%u:%u] "

+ 13 - 3
modules/dialog/dlg_handlers.c

@@ -524,6 +524,11 @@ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
 		goto done;
 	}
 
+	if(new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
+		/* set end time */
+		dlg->end_ts = (unsigned int)(time(0));
+	}
+
 	if ( new_state==DLG_STATE_DELETED
 				&& (old_state==DLG_STATE_UNCONFIRMED
 					|| old_state==DLG_STATE_EARLY) ) {
@@ -1280,7 +1285,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 			iuid = NULL;
 		}
 	}
-	
+
 	/* run state machine */
 	switch ( req->first_line.u.request.method_value ) {
 		case METHOD_PRACK:
@@ -1304,6 +1309,8 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
 	/* delay deletion of dialog until transaction has died off in order
 	 * to absorb in-air messages */
 	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
+		/* set end time */
+		dlg->end_ts = (unsigned int)(time(0));
 		iuid = dlg_get_iuid_shm_clone(dlg);
 		if(iuid!=NULL) {
 			if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
@@ -1478,7 +1485,7 @@ void dlg_ontimeout(struct dlg_tl *tl)
 			dlg_set_ctx_iuid(dlg);
 			if(dlg_bye_all(dlg, NULL)<0)
 				dlg_unref(dlg, 1);
-			dlg_reset_ctx_iuid();	
+			dlg_reset_ctx_iuid();
 
 			dlg_unref(dlg, 1);
 			if_update_stat(dlg_enable_stats, expired_dlgs, 1);
@@ -1490,7 +1497,7 @@ void dlg_ontimeout(struct dlg_tl *tl)
     /* used for computing duration for timed out acknowledged dialog */
 	if (DLG_STATE_CONFIRMED == old_state) {
 		timeout_cb = (void *)CONFIRMED_DIALOG_STATE;
-	}	
+	}
 
 	dlg_run_event_route(dlg, NULL, old_state, new_state);
 
@@ -1500,6 +1507,9 @@ void dlg_ontimeout(struct dlg_tl *tl)
 			dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
 			dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
 
+		/* set end time */
+		dlg->end_ts = (unsigned int)(time(0));
+
 		/* dialog timeout */
 		run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb);
 

+ 7 - 0
modules/dialog/dlg_hash.c

@@ -239,6 +239,13 @@ int dlg_clean_run(ticks_t ti)
 				tdlg->lifetime = 10;
 				tdlg->dflags |= DLG_FLAG_CHANGED;
 			}
+			if(tdlg->state==DLG_STATE_DELETED && tdlg->end_ts<tm-300) {
+				/* dialog in deleted state older than 5min */
+				LM_NOTICE("dialog in delete state is too old (%p ref %d)\n",
+						tdlg, tdlg->ref);
+				unlink_unsafe_dlg(&d_table->entries[i], tdlg);
+				destroy_dlg(tdlg);
+			}
 		}
 		dlg_unlock(d_table, &d_table->entries[i]);
 	}

+ 1 - 0
modules/dialog/dlg_hash.h

@@ -108,6 +108,7 @@ typedef struct dlg_cell
 	unsigned int         lifetime;		/*!< dialog lifetime */
 	unsigned int         init_ts;		/*!< init (creation) time (absolute UNIX ts)*/
 	unsigned int         start_ts;		/*!< start time  (absolute UNIX ts)*/
+	unsigned int         end_ts;		/*!< end time  (absolute UNIX ts)*/
 	unsigned int         dflags;		/*!< internal dialog memory flags */
 	unsigned int         iflags;		/*!< internal dialog persistent flags */
 	unsigned int         sflags;		/*!< script dialog persistent flags */