diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 8601a32a4ed69f1d5f5c4b04d8f66c3bbe86b7dc..ed4f8d5ca1c609fba1ffb56d5dae720bf6114dbc 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -324,14 +324,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 static const char app[] = "ConfBridge";
 
-/* Number of buckets our conference bridges container can have */
+/*! Number of buckets our conference bridges container can have */
 #define CONFERENCE_BRIDGE_BUCKETS 53
 
-enum {
-	CONF_RECORD_EXIT = 0,
-	CONF_RECORD_START,
-	CONF_RECORD_STOP,
-};
+/*! Initial recording filename space. */
+#define RECORD_FILENAME_INITIAL_SPACE	128
 
 /*! \brief Container to hold all conference bridges in progress */
 struct ao2_container *conference_bridges;
@@ -594,10 +591,11 @@ static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
 {
 	if (!ast_strlen_zero(rec_file)) {
 		if (!*orig_rec_file) {
-			*orig_rec_file = ast_str_create(PATH_MAX);
+			*orig_rec_file = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
 		}
 
-		if (strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
+		if (*orig_rec_file
+			&& strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
 			ast_str_set(orig_rec_file, 0, "%s", rec_file);
 			return 1;
 		}
@@ -605,79 +603,48 @@ static int is_new_rec_file(const char *rec_file, struct ast_str **orig_rec_file)
 	return 0;
 }
 
-static void *record_thread(void *obj)
-{
-	struct confbridge_conference *conference = obj;
-	struct ast_app *mixmonapp = pbx_findapp("MixMonitor");
-	struct ast_channel *chan;
-	struct ast_str *filename = ast_str_alloca(PATH_MAX);
-	struct ast_str *orig_rec_file = NULL;
-	struct ast_bridge_features features;
-
-	ast_mutex_lock(&conference->record_lock);
-	if (!mixmonapp) {
-		ast_log(LOG_WARNING, "Can not record ConfBridge, MixMonitor app is not installed\n");
-		conference->record_thread = AST_PTHREADT_NULL;
-		ast_mutex_unlock(&conference->record_lock);
-		ao2_ref(conference, -1);
-		return NULL;
-	}
-	if (ast_bridge_features_init(&features)) {
-		ast_bridge_features_cleanup(&features);
-		conference->record_thread = AST_PTHREADT_NULL;
-		ast_mutex_unlock(&conference->record_lock);
-		ao2_ref(conference, -1);
-		return NULL;
-	}
-	ast_set_flag(&features.feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
-
-	/* XXX If we get an EXIT right here, START will essentially be a no-op */
-	while (conference->record_state != CONF_RECORD_EXIT) {
-		set_rec_filename(conference, &filename,
-			is_new_rec_file(conference->b_profile.rec_file, &orig_rec_file));
-		chan = ast_channel_ref(conference->record_chan);
-		ast_answer(chan);
-		pbx_exec(chan, mixmonapp, ast_str_buffer(filename));
-		ast_bridge_join(conference->bridge, chan, NULL, &features, NULL, 0);
-
-		ast_hangup(chan); /* This will eat this thread's reference to the channel as well */
-		/* STOP has been called. Wait for either a START or an EXIT */
-		ast_cond_wait(&conference->record_cond, &conference->record_lock);
-	}
-	ast_bridge_features_cleanup(&features);
-	ast_free(orig_rec_file);
-	ast_mutex_unlock(&conference->record_lock);
-	ao2_ref(conference, -1);
-	return NULL;
-}
-
-/*! \brief Returns whether or not conference is being recorded.
+/*!
+ * \internal
+ * \brief Returns whether or not conference is being recorded.
+ *
  * \param conference The bridge to check for recording
+ *
+ * \note Must be called with the conference locked
+ *
  * \retval 1, conference is recording.
  * \retval 0, conference is NOT recording.
  */
 static int conf_is_recording(struct confbridge_conference *conference)
 {
-	return conference->record_state == CONF_RECORD_START;
+	return conference->record_chan != NULL;
 }
 
-/*! \brief Stop recording a conference bridge
+/*!
  * \internal
+ * \brief Stop recording a conference bridge
+ *
  * \param conference The conference bridge on which to stop the recording
+ *
+ * \note Must be called with the conference locked
+ *
  * \retval -1 Failure
  * \retval 0 Success
  */
 static int conf_stop_record(struct confbridge_conference *conference)
 {
 	struct ast_channel *chan;
-	if (conference->record_thread == AST_PTHREADT_NULL || !conf_is_recording(conference)) {
+	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
+
+	if (!conf_is_recording(conference)) {
 		return -1;
 	}
-	conference->record_state = CONF_RECORD_STOP;
-	chan = ast_channel_ref(conference->record_chan);
-	ast_bridge_remove(conference->bridge, chan);
-	ast_queue_frame(chan, &ast_null_frame);
-	chan = ast_channel_unref(chan);
+
+	/* Remove the recording channel from the conference bridge. */
+	chan = conference->record_chan;
+	conference->record_chan = NULL;
+	ast_queue_frame(chan, &f);
+	ast_channel_unref(chan);
+
 	ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
 	send_stop_record_event(conference);
 
@@ -686,102 +653,73 @@ static int conf_stop_record(struct confbridge_conference *conference)
 
 /*!
  * \internal
- * \brief Stops the confbridge recording thread.
+ * \brief Start recording the conference
  *
- * \note Must be called with the conference locked
- */
-static int conf_stop_record_thread(struct confbridge_conference *conference)
-{
-	if (conference->record_thread == AST_PTHREADT_NULL) {
-		return -1;
-	}
-	conf_stop_record(conference);
-
-	ast_mutex_lock(&conference->record_lock);
-	conference->record_state = CONF_RECORD_EXIT;
-	ast_cond_signal(&conference->record_cond);
-	ast_mutex_unlock(&conference->record_lock);
-
-	pthread_join(conference->record_thread, NULL);
-	conference->record_thread = AST_PTHREADT_NULL;
-
-	/* this is the reference given to the channel during the channel alloc */
-	if (conference->record_chan) {
-		conference->record_chan = ast_channel_unref(conference->record_chan);
-	}
-
-	return 0;
-}
-
-/*! \brief Start recording the conference
- * \internal
- * \note The conference must be locked when calling this function
  * \param conference The conference bridge to start recording
+ *
+ * \note Must be called with the conference locked
+ *
  * \retval 0 success
- * \rteval non-zero failure
+ * \retval non-zero failure
  */
 static int conf_start_record(struct confbridge_conference *conference)
 {
+	struct ast_app *mixmonapp;
+	struct ast_channel *chan;
 	struct ast_format_cap *cap;
+	struct ast_bridge_features *features;
+
+	if (conf_is_recording(conference)) {
+		return -1;
+	}
 
-	if (conference->record_state != CONF_RECORD_STOP) {
+	mixmonapp = pbx_findapp("MixMonitor");
+	if (!mixmonapp) {
+		ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
 		return -1;
 	}
 
-	if (!pbx_findapp("MixMonitor")) {
-		ast_log(LOG_WARNING, "Can not record ConfBridge, MixMonitor app is not installed\n");
+	features = ast_bridge_features_new();
+	if (!features) {
 		return -1;
 	}
+	ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
 
 	cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
 	if (!cap) {
+		ast_bridge_features_destroy(features);
 		return -1;
 	}
-
 	ast_format_cap_append(cap, ast_format_slin, 0);
 
-	conference->record_chan = ast_request("CBRec", cap, NULL, NULL,
-		conference->name, NULL);
+	/* Create the recording channel. */
+	chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
 	ao2_ref(cap, -1);
-	if (!conference->record_chan) {
+	if (!chan) {
+		ast_bridge_features_destroy(features);
 		return -1;
 	}
 
-	conference->record_state = CONF_RECORD_START;
-	ast_mutex_lock(&conference->record_lock);
-	ast_cond_signal(&conference->record_cond);
-	ast_mutex_unlock(&conference->record_lock);
-	ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
-	send_start_record_event(conference);
-
-	return 0;
-}
-
-/*! \brief Start the recording thread on a conference bridge
- * \internal
- * \param conference The conference bridge on which to start the recording thread
- * \retval 0 success
- * \retval -1 failure
- */
-static int start_conf_record_thread(struct confbridge_conference *conference)
-{
-	conf_start_record(conference);
-
-	/*
-	 * if the thread has already been started, don't start another
-	 */
-	if (conference->record_thread != AST_PTHREADT_NULL) {
-		return 0;
-	}
-
-	ao2_ref(conference, +1); /* give the record thread a ref */
-
-	if (ast_pthread_create_background(&conference->record_thread, NULL, record_thread, conference)) {
-		ast_log(LOG_WARNING, "Failed to create recording channel for conference %s\n", conference->name);
-		ao2_ref(conference, -1); /* error so remove ref */
+	/* Start recording. */
+	set_rec_filename(conference, &conference->record_filename,
+		is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
+	ast_answer(chan);
+	pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
+
+	/* Put the channel into the conference bridge. */
+	ast_channel_ref(chan);
+	conference->record_chan = chan;
+	if (ast_bridge_impart(conference->bridge, chan, NULL, features,
+		AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
+		ast_hangup(chan);
+		ast_channel_unref(chan);
+		conference->record_chan = NULL;
 		return -1;
 	}
 
+	ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
+	send_start_record_event(conference);
+
 	return 0;
 }
 
@@ -967,9 +905,11 @@ static void destroy_conference_bridge(void *obj)
 		conference->bridge = NULL;
 	}
 
+	ast_channel_cleanup(conference->record_chan);
+	ast_free(conference->orig_rec_file);
+	ast_free(conference->record_filename);
+
 	conf_bridge_profile_destroy(&conference->b_profile);
-	ast_cond_destroy(&conference->record_cond);
-	ast_mutex_destroy(&conference->record_lock);
 	ast_mutex_destroy(&conference->playback_lock);
 }
 
@@ -1212,7 +1152,9 @@ void conf_ended(struct confbridge_conference *conference)
 	/* Called with a reference to conference */
 	ao2_unlink(conference_bridges, conference);
 	send_conf_end_event(conference);
-	conf_stop_record_thread(conference);
+	ao2_lock(conference);
+	conf_stop_record(conference);
+	ao2_unlock(conference);
 }
 
 /*!
@@ -1263,12 +1205,15 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
 		/* Setup lock for playback channel */
 		ast_mutex_init(&conference->playback_lock);
 
-		/* Setup lock for the record channel */
-		ast_mutex_init(&conference->record_lock);
-		ast_cond_init(&conference->record_cond, NULL);
+		/* Setup for the record channel */
+		conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
+		if (!conference->record_filename) {
+			ao2_ref(conference, -1);
+			ao2_unlock(conference_bridges);
+			return NULL;
+		}
 
 		/* Setup conference bridge parameters */
-		conference->record_thread = AST_PTHREADT_NULL;
 		ast_copy_string(conference->name, conference_name, sizeof(conference->name));
 		conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
 
@@ -1306,10 +1251,9 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
 		/* Set the initial state to EMPTY */
 		conference->state = CONF_STATE_EMPTY;
 
-		conference->record_state = CONF_RECORD_STOP;
 		if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
 			ao2_lock(conference);
-			start_conf_record_thread(conference);
+			conf_start_record(conference);
 			ao2_unlock(conference);
 		}
 
@@ -2758,7 +2702,7 @@ static char *handle_cli_confbridge_start_record(struct ast_cli_entry *e, int cmd
 		ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
 	}
 
-	if (start_conf_record_thread(conference)) {
+	if (conf_start_record(conference)) {
 		ast_cli(a->fd, "Could not start recording due to internal error.\n");
 		ao2_unlock(conference);
 		ao2_ref(conference, -1);
@@ -3092,7 +3036,7 @@ static int action_confbridgestartrecord(struct mansession *s, const struct messa
 		ast_copy_string(conference->b_profile.rec_file, recordfile, sizeof(conference->b_profile.rec_file));
 	}
 
-	if (start_conf_record_thread(conference)) {
+	if (conf_start_record(conference)) {
 		astman_send_error(s, m, "Internal error starting conference recording.");
 		ao2_unlock(conference);
 		ao2_ref(conference, -1);
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index 5488065ca8430c0165251d165e58b98b25f515f0..54a9dc4ec20a72b2f9957f78959b438a2dbecc30 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -221,13 +221,11 @@ struct confbridge_conference {
 	unsigned int waitingusers;                                        /*!< Number of waiting users present */
 	unsigned int locked:1;                                            /*!< Is this conference bridge locked? */
 	unsigned int muted:1;                                             /*!< Is this conference bridge muted? */
-	unsigned int record_state:2;                                      /*!< Whether recording is started, stopped, or should exit */
 	struct ast_channel *playback_chan;                                /*!< Channel used for playback into the conference bridge */
 	struct ast_channel *record_chan;                                  /*!< Channel used for recording the conference */
-	pthread_t record_thread;                                          /*!< The thread the recording chan lives in */
+	struct ast_str *record_filename;                                  /*!< Recording filename. */
+	struct ast_str *orig_rec_file;                                    /*!< Previous b_profile.rec_file. */
 	ast_mutex_t playback_lock;                                        /*!< Lock used for playback channel */
-	ast_mutex_t record_lock;                                          /*!< Lock used for the record thread */
-	ast_cond_t record_cond;                                           /*!< Recording condition variable */
 	AST_LIST_HEAD_NOLOCK(, confbridge_user) active_list;              /*!< List of users participating in the conference bridge */
 	AST_LIST_HEAD_NOLOCK(, confbridge_user) waiting_list;             /*!< List of users waiting to join the conference bridge */
 };