[svn-commits] jrose: branch 12 r421879 - in /branches/12: include/asterisk/ res/ res/stasis/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Aug 22 11:27:51 CDT 2014


Author: jrose
Date: Fri Aug 22 11:27:42 2014
New Revision: 421879

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=421879
Log:
ARI: Fix a crash caused by hanging during playback to a channel in a bridge

ASTERISK-24147 #close
Reported by: Edvin Vidmar
Review: https://reviewboard.asterisk.org/r/3908/

Modified:
    branches/12/include/asterisk/stasis_app_impl.h
    branches/12/res/res_stasis.c
    branches/12/res/res_stasis_answer.c
    branches/12/res/res_stasis_playback.c
    branches/12/res/res_stasis_recording.c
    branches/12/res/stasis/command.c
    branches/12/res/stasis/command.h
    branches/12/res/stasis/control.c
    branches/12/res/stasis/stasis_bridge.c

Modified: branches/12/include/asterisk/stasis_app_impl.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/stasis_app_impl.h?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/include/asterisk/stasis_app_impl.h (original)
+++ branches/12/include/asterisk/stasis_app_impl.h Fri Aug 22 11:27:42 2014
@@ -48,6 +48,19 @@
 int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
 	char *argv[]);
 
+/*!
+ * \brief Typedef for data destructor for stasis app commands
+ *
+ * \param data Data to destroy.
+ *
+ * \details
+ * This is called during destruction of the command or if we fail to schedule
+ * a command. It is passed a pointer to the user-defined data of the command.
+ *
+ * \return Nothing
+ */
+typedef void (*command_data_destructor_fn)(void *data);
+
 /*! Callback type for stasis app commands */
 typedef int (*stasis_app_command_cb)(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data);
@@ -63,16 +76,19 @@
  * \param control Control object for the channel to send the command to.
  * \param command Command function to execute.
  * \param data Optional data to pass along with the control function.
+ * \param data_destructor Optional function which will be called on
+ *        the data in either the event of command completion or failure
+ *        to schedule or complete the command
  *
  * \return zero on success.
  * \return error code otherwise.
  */
 int stasis_app_send_command(struct stasis_app_control *control,
-	stasis_app_command_cb command, void *data);
+	stasis_app_command_cb command, void *data, command_data_destructor_fn data_destructor);
 
 /*!
  * \since 12
- * \brief Asynchronous version of stasis_app_send().
+ * \brief Asynchronous version of stasis_app_send_command().
  *
  * This function enqueues a command for execution, but returns immediately
  * without waiting for the response.
@@ -80,10 +96,13 @@
  * \param control Control object for the channel to send the command to.
  * \param command Command function to execute.
  * \param data Optional data to pass along with the control function.
+ * \param data_destructor Optional function which will be called on
+ *        the data in either the event of command completion or failure
+ *        to schedule or complete the command
  * \return 0 on success.
  * \return Non-zero on error.
  */
 int stasis_app_send_command_async(struct stasis_app_control *control,
-	stasis_app_command_cb command, void *data);
+	stasis_app_command_cb command, void *data, command_data_destructor_fn data_destructor);
 
 #endif /* _ASTERISK_RES_STASIS_H */

Modified: branches/12/res/res_stasis.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_stasis.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/res_stasis.c (original)
+++ branches/12/res/res_stasis.c Fri Aug 22 11:27:42 2014
@@ -1190,6 +1190,7 @@
 	RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
 	struct ast_bridge *bridge = NULL;
 	int res = 0;
+	int needs_depart;
 
 	ast_assert(chan != NULL);
 
@@ -1303,6 +1304,13 @@
 				break;
 			}
 		}
+	}
+
+	ast_channel_lock(chan);
+	needs_depart = ast_channel_is_bridged(chan);
+	ast_channel_unlock(chan);
+	if (needs_depart) {
+		ast_bridge_depart(chan);
 	}
 
 	app_unsubscribe_bridge(app, stasis_app_get_bridge(control));

Modified: branches/12/res/res_stasis_answer.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_stasis_answer.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/res_stasis_answer.c (original)
+++ branches/12/res/res_stasis_answer.c Fri Aug 22 11:27:42 2014
@@ -50,7 +50,7 @@
 	ast_debug(3, "%s: Sending answer command\n",
 		stasis_app_control_get_channel_id(control));
 
-	retval = stasis_app_send_command(control, app_control_answer, NULL);
+	retval = stasis_app_send_command(control, app_control_answer, NULL, NULL);
 
 	if (retval != 0) {
 		ast_log(LOG_WARNING, "%s: Failed to answer channel\n",

Modified: branches/12/res/res_stasis_playback.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_stasis_playback.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/res_stasis_playback.c (original)
+++ branches/12/res/res_stasis_playback.c Fri Aug 22 11:27:42 2014
@@ -366,20 +366,20 @@
  * \brief \ref RAII_VAR function to remove a playback from the global list when
  * leaving scope.
  */
-static void remove_from_playbacks(struct stasis_app_playback *playback)
-{
+static void remove_from_playbacks(void *data)
+{
+	struct stasis_app_playback *playback = data;
+
 	ao2_unlink_flags(playbacks, playback,
 		OBJ_POINTER | OBJ_UNLINK | OBJ_NODATA);
+	ao2_ref(playback, -1);
 }
 
 static int play_uri(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_playback *, playback, NULL,
-		remove_from_playbacks);
+	struct stasis_app_playback *playback = data;
 	struct ast_bridge *bridge;
-
-	playback = data;
 
 	if (!control) {
 		return -1;
@@ -434,7 +434,7 @@
 	enum stasis_app_playback_target_type target_type,
 	int skipms, long offsetms, const char *id)
 {
-	RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
+	struct stasis_app_playback *playback;
 
 	if (skipms < 0 || offsetms < 0) {
 		return NULL;
@@ -444,6 +444,9 @@
 		stasis_app_control_get_channel_id(control), uri);
 
 	playback = playback_create(control, id);
+	if (!playback) {
+		return NULL;
+	}
 
 	if (skipms == 0) {
 		skipms = PLAYBACK_DEFAULT_SKIPMS;
@@ -459,11 +462,8 @@
 	playback->state = STASIS_PLAYBACK_STATE_QUEUED;
 	playback_publish(playback);
 
-	/* A ref is kept in the playbacks container; no need to bump */
-	stasis_app_send_command_async(control, play_uri, playback);
-
-	/* Although this should be bumped for the caller */
-	ao2_ref(playback, +1);
+	stasis_app_send_command_async(control, play_uri, ao2_bump(playback), remove_from_playbacks);
+
 	return playback;
 }
 

Modified: branches/12/res/res_stasis_recording.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_stasis_recording.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/res_stasis_recording.c (original)
+++ branches/12/res/res_stasis_recording.c Fri Aug 22 11:27:42 2014
@@ -279,21 +279,22 @@
 		recording, STASIS_APP_RECORDING_STATE_FAILED, cause);
 }
 
-static void recording_cleanup(struct stasis_app_recording *recording)
-{
+static void recording_cleanup(void *data)
+{
+	struct stasis_app_recording *recording = data;
+
 	ao2_unlink_flags(recordings, recording,
 		OBJ_POINTER | OBJ_UNLINK | OBJ_NODATA);
+	ao2_ref(recording, -1);
 }
 
 static int record_file(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_recording *, recording,
-		NULL, recording_cleanup);
+	struct stasis_app_recording *recording = data;
 	char *acceptdtmf;
 	int res;
 
-	recording = data;
 	ast_assert(recording != NULL);
 
 	if (stasis_app_get_bridge(control)) {
@@ -364,7 +365,7 @@
 	struct stasis_app_control *control,
 	struct stasis_app_recording_options *options)
 {
-	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+	struct stasis_app_recording *recording;
 	char *last_slash;
 
 	errno = 0;
@@ -395,6 +396,7 @@
 
 	if (recording->absolute_name == NULL) {
 		errno = ENOMEM;
+		ao2_ref(recording, -1);
 		return NULL;
 	}
 
@@ -403,6 +405,7 @@
 		if (ast_safe_mkdir(ast_config_AST_RECORDING_DIR,
 				recording->absolute_name, 0777) != 0) {
 			/* errno set by ast_mkdir */
+			ao2_ref(recording, -1);
 			return NULL;
 		}
 		*last_slash = '/';
@@ -418,6 +421,7 @@
 		ast_log(LOG_WARNING, "Recording file '%s' already exists and ifExists option is failure.\n",
 			recording->absolute_name);
 		errno = EEXIST;
+		ao2_ref(recording, -1);
 		return NULL;
 	}
 
@@ -434,6 +438,7 @@
 				"Recording %s already in progress\n",
 				recording->options->name);
 			errno = EEXIST;
+			ao2_ref(recording, -1);
 			return NULL;
 		}
 		ao2_link(recordings, recording);
@@ -441,11 +446,8 @@
 
 	stasis_app_control_register_add_rule(control, &rule_recording);
 
-	/* A ref is kept in the recordings container; no need to bump */
-	stasis_app_send_command_async(control, record_file, recording);
-
-	/* Although this should be bumped for the caller */
-	ao2_ref(recording, +1);
+	stasis_app_send_command_async(control, record_file, ao2_bump(recording), recording_cleanup);
+
 	return recording;
 }
 

Modified: branches/12/res/stasis/command.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/stasis/command.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/stasis/command.c (original)
+++ branches/12/res/stasis/command.c Fri Aug 22 11:27:42 2014
@@ -37,6 +37,7 @@
 	ast_cond_t condition;
 	stasis_app_command_cb callback;
 	void *data;
+	command_data_destructor_fn data_destructor;
 	int retval;
 	int is_done:1;
 };
@@ -44,17 +45,25 @@
 static void command_dtor(void *obj)
 {
 	struct stasis_app_command *command = obj;
+
+	if (command->data_destructor) {
+		command->data_destructor(command->data);
+	}
+
 	ast_mutex_destroy(&command->lock);
 	ast_cond_destroy(&command->condition);
 }
 
 struct stasis_app_command *command_create(
-	stasis_app_command_cb callback, void *data)
+	stasis_app_command_cb callback, void *data, command_data_destructor_fn data_destructor)
 {
-	RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
+	struct stasis_app_command *command;
 
 	command = ao2_alloc(sizeof(*command), command_dtor);
 	if (!command) {
+		if (data_destructor) {
+			data_destructor(data);
+		}
 		return NULL;
 	}
 
@@ -62,8 +71,8 @@
 	ast_cond_init(&command->condition, 0);
 	command->callback = callback;
 	command->data = data;
+	command->data_destructor = data_destructor;
 
-	ao2_ref(command, +1);
 	return command;
 }
 
@@ -90,6 +99,10 @@
 	struct stasis_app_control *control, struct ast_channel *chan)
 {
 	int retval = command->callback(control, chan, command->data);
+	if (command->data_destructor) {
+		command->data_destructor(command->data);
+		command->data_destructor = NULL;
+	}
 	command_complete(command, retval);
 }
 
@@ -105,12 +118,12 @@
 };
 
 int command_prestart_queue_command(struct ast_channel *chan,
-	stasis_app_command_cb command_fn, void *data)
+	stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 {
 	struct ast_datastore *datastore;
 	struct ao2_container *command_queue;
 	RAII_VAR(struct stasis_app_command *, command,
-		command_create(command_fn, data), ao2_cleanup);
+		command_create(command_fn, data, data_destructor), ao2_cleanup);
 
 	if (!command) {
 		return -1;

Modified: branches/12/res/stasis/command.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/stasis/command.h?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/stasis/command.h (original)
+++ branches/12/res/stasis/command.h Fri Aug 22 11:27:42 2014
@@ -32,7 +32,8 @@
 struct stasis_app_command;
 
 struct stasis_app_command *command_create(
-	stasis_app_command_cb callback, void *data);
+	stasis_app_command_cb callback, void *data,
+	command_data_destructor_fn data_destructor);
 
 void command_complete(struct stasis_app_command *command, int retval);
 
@@ -49,12 +50,16 @@
  * \param chan The channel on which to queue the prestart command
  * \param command_fn The callback to call for the command
  * \param data The data to pass to the command callback
+ * \param data_destructor Optional function which will be called on
+ *        the data in either the event of command completion or failure
+ *        to schedule or complete the command
  *
  * \retval zero on success
  * \retval non-zero on failure
  */
 int command_prestart_queue_command(struct ast_channel *chan,
-	stasis_app_command_cb command_fn, void *data);
+	stasis_app_command_cb command_fn, void *data,
+	command_data_destructor_fn data_destructor);
 
 /*!
  * \brief Get the Stasis() prestart commands for a channel

Modified: branches/12/res/stasis/control.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/stasis/control.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/stasis/control.c (original)
+++ branches/12/res/stasis/control.c Fri Aug 22 11:27:42 2014
@@ -238,14 +238,15 @@
 
 static struct stasis_app_command *exec_command_on_condition(
 	struct stasis_app_control *control, stasis_app_command_cb command_fn,
-	void *data, app_command_can_exec_cb can_exec_fn)
+	void *data, command_data_destructor_fn data_destructor,
+	app_command_can_exec_cb can_exec_fn)
 {
 	int retval;
 	struct stasis_app_command *command;
 
 	command_fn = command_fn ? : noop_cb;
 
-	command = command_create(command_fn, data);
+	command = command_create(command_fn, data, data_destructor);
 	if (!command) {
 		return NULL;
 	}
@@ -266,9 +267,9 @@
 
 static struct stasis_app_command *exec_command(
 	struct stasis_app_control *control, stasis_app_command_cb command_fn,
-	void *data)
-{
-	return exec_command_on_condition(control, command_fn, data, NULL);
+	void *data, command_data_destructor_fn data_destructor)
+{
+	return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
 }
 
 struct stasis_app_control_dial_data {
@@ -280,7 +281,7 @@
 	struct ast_channel *chan, void *data)
 {
 	RAII_VAR(struct ast_dial *, dial, ast_dial_create(), ast_dial_destroy);
-	RAII_VAR(struct stasis_app_control_dial_data *, dial_data, data, ast_free);
+	struct stasis_app_control_dial_data *dial_data = data;
 	enum ast_dial_result res;
 	char *tech, *resource;
 	struct ast_channel *new_chan;
@@ -349,7 +350,7 @@
 		dial_data->timeout = 30000;
 	}
 
-	stasis_app_send_command_async(control, app_control_dial, dial_data);
+	stasis_app_send_command_async(control, app_control_dial, dial_data, ast_free_ptr);
 
 	return 0;
 }
@@ -389,7 +390,7 @@
 static int app_control_continue(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_control_continue_data *, continue_data, data, ast_free);
+	struct stasis_app_control_continue_data *continue_data = data;
 
 	ast_assert(control->channel != NULL);
 
@@ -422,7 +423,7 @@
 		continue_data->priority = -1;
 	}
 
-	stasis_app_send_command_async(control, app_control_continue, continue_data);
+	stasis_app_send_command_async(control, app_control_continue, continue_data, ast_free_ptr);
 
 	return 0;
 }
@@ -438,7 +439,7 @@
 static int app_control_dtmf(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_control_dtmf_data *, dtmf_data, data, ast_free);
+	struct stasis_app_control_dtmf_data *dtmf_data = data;
 
 	if (ast_channel_state(chan) != AST_STATE_UP) {
 		ast_indicate(chan, AST_CONTROL_PROGRESS);
@@ -471,7 +472,7 @@
 	dtmf_data->after = after;
 	strcpy(dtmf_data->dtmf, dtmf);
 
-	stasis_app_send_command_async(control, app_control_dtmf, dtmf_data);
+	stasis_app_send_command_async(control, app_control_dtmf, dtmf_data, ast_free_ptr);
 
 	return 0;
 }
@@ -486,7 +487,7 @@
 
 int stasis_app_control_ring(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_ring, NULL);
+	stasis_app_send_command_async(control, app_control_ring, NULL, NULL);
 
 	return 0;
 }
@@ -501,7 +502,7 @@
 
 int stasis_app_control_ring_stop(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_ring_stop, NULL);
+	stasis_app_send_command_async(control, app_control_ring_stop, NULL, NULL);
 
 	return 0;
 }
@@ -514,7 +515,7 @@
 static int app_control_mute(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_control_mute_data *, mute_data, data, ast_free);
+	struct stasis_app_control_mute_data *mute_data = data;
 	SCOPED_CHANNELLOCK(lockvar, chan);
 
 	ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
@@ -533,7 +534,7 @@
 	mute_data->direction = direction;
 	mute_data->frametype = frametype;
 
-	stasis_app_send_command_async(control, app_control_mute, mute_data);
+	stasis_app_send_command_async(control, app_control_mute, mute_data, ast_free_ptr);
 
 	return 0;
 }
@@ -541,7 +542,7 @@
 static int app_control_unmute(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct stasis_app_control_mute_data *, mute_data, data, ast_free);
+	struct stasis_app_control_mute_data *mute_data = data;
 	SCOPED_CHANNELLOCK(lockvar, chan);
 
 	ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
@@ -560,7 +561,7 @@
 	mute_data->direction = direction;
 	mute_data->frametype = frametype;
 
-	stasis_app_send_command_async(control, app_control_unmute, mute_data);
+	stasis_app_send_command_async(control, app_control_unmute, mute_data, ast_free_ptr);
 
 	return 0;
 }
@@ -608,7 +609,7 @@
 
 void stasis_app_control_hold(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_hold, NULL);
+	stasis_app_send_command_async(control, app_control_hold, NULL, NULL);
 }
 
 static int app_control_unhold(struct stasis_app_control *control,
@@ -621,7 +622,7 @@
 
 void stasis_app_control_unhold(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_unhold, NULL);
+	stasis_app_send_command_async(control, app_control_unhold, NULL, NULL);
 }
 
 static int app_control_moh_start(struct stasis_app_control *control,
@@ -635,7 +636,6 @@
 
 	ast_moh_start(chan, moh_class, NULL);
 
-	ast_free(moh_class);
 	return 0;
 }
 
@@ -647,7 +647,7 @@
 		data = ast_strdup(moh_class);
 	}
 
-	stasis_app_send_command_async(control, app_control_moh_start, data);
+	stasis_app_send_command_async(control, app_control_moh_start, data, ast_free_ptr);
 }
 
 static int app_control_moh_stop(struct stasis_app_control *control,
@@ -659,7 +659,7 @@
 
 void stasis_app_control_moh_stop(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_moh_stop, NULL);
+	stasis_app_send_command_async(control, app_control_moh_stop, NULL, NULL);
 }
 
 static int app_control_silence_start(struct stasis_app_control *control,
@@ -693,7 +693,7 @@
 
 void stasis_app_control_silence_start(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_silence_start, NULL);
+	stasis_app_send_command_async(control, app_control_silence_start, NULL, NULL);
 }
 
 static int app_control_silence_stop(struct stasis_app_control *control,
@@ -712,7 +712,7 @@
 
 void stasis_app_control_silence_stop(struct stasis_app_control *control)
 {
-	stasis_app_send_command_async(control, app_control_silence_stop, NULL);
+	stasis_app_send_command_async(control, app_control_silence_stop, NULL, NULL);
 }
 
 struct ast_channel_snapshot *stasis_app_control_get_snapshot(
@@ -736,6 +736,7 @@
 
 static int app_send_command_on_condition(struct stasis_app_control *control,
 					 stasis_app_command_cb command_fn, void *data,
+					 command_data_destructor_fn data_destructor,
 					 app_command_can_exec_cb can_exec_fn)
 {
 	RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
@@ -745,7 +746,7 @@
 	}
 
 	command = exec_command_on_condition(
-		control, command_fn, data, can_exec_fn);
+		control, command_fn, data, data_destructor, can_exec_fn);
 	if (!command) {
 		return -1;
 	}
@@ -754,13 +755,14 @@
 }
 
 int stasis_app_send_command(struct stasis_app_control *control,
-	stasis_app_command_cb command_fn, void *data)
-{
-	return app_send_command_on_condition(control, command_fn, data, NULL);
+	stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
+{
+	return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
 }
 
 int stasis_app_send_command_async(struct stasis_app_control *control,
-	stasis_app_command_cb command_fn, void *data)
+	stasis_app_command_cb command_fn, void *data,
+	command_data_destructor_fn data_destructor)
 {
 	RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
 
@@ -768,7 +770,7 @@
 		return -1;
 	}
 
-	command = exec_command(control, command_fn, data);
+	command = exec_command(control, command_fn, data, data_destructor);
 	if (!command) {
 		return -1;
 	}
@@ -789,7 +791,7 @@
 static int bridge_channel_depart(struct stasis_app_control *control,
 	struct ast_channel *chan, void *data)
 {
-	RAII_VAR(struct ast_bridge_channel *, bridge_channel, data, ao2_cleanup);
+	struct ast_bridge_channel *bridge_channel = data;
 
 	{
 		SCOPED_CHANNELLOCK(lock, chan);
@@ -835,9 +837,7 @@
 	ast_channel_unlock(chan);
 
 	/* Depart this channel from the bridge using the command queue if possible */
-	if (stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel)) {
-		ao2_cleanup(bridge_channel);
-	}
+	stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup);
 	if (stasis_app_channel_is_stasis_end_published(chan)) {
 		/* The channel has had a StasisEnd published on it, but until now had remained in
 		 * the bridging system. This means that the channel moved from a Stasis bridge to a
@@ -946,7 +946,7 @@
 			stasis_app_control_get_channel_id(control));
 
 	return app_send_command_on_condition(
-		control, control_add_channel_to_bridge, bridge,
+		control, control_add_channel_to_bridge, bridge, NULL,
 		app_control_can_add_channel_to_bridge);
 }
 
@@ -982,7 +982,7 @@
 	ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
 			stasis_app_control_get_channel_id(control));
 	return app_send_command_on_condition(
-		control, app_control_remove_channel_from_bridge, bridge,
+		control, app_control_remove_channel_from_bridge, bridge, NULL,
 		app_control_can_remove_channel_from_bridge);
 }
 

Modified: branches/12/res/stasis/stasis_bridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/stasis/stasis_bridge.c?view=diff&rev=421879&r1=421878&r2=421879
==============================================================================
--- branches/12/res/stasis/stasis_bridge.c (original)
+++ branches/12/res/stasis/stasis_bridge.c Fri Aug 22 11:27:42 2014
@@ -85,7 +85,6 @@
 
 	res = control_add_channel_to_bridge(control,
 		chan, bridge);
-	ao2_cleanup(bridge);
 	return res;
 }
 
@@ -93,9 +92,8 @@
 	struct ast_bridge_channel *bridge_channel)
 {
 	ast_channel_lock(bridge_channel->chan);
-	if (command_prestart_queue_command(bridge_channel->chan, add_channel_to_bridge, ao2_bump(self))) {
-		ao2_cleanup(self);
-	}
+	command_prestart_queue_command(bridge_channel->chan, add_channel_to_bridge,
+		ao2_bump(self), __ao2_cleanup);
 	ast_channel_unlock(bridge_channel->chan);
 }
 




More information about the svn-commits mailing list