diff --git a/res/res_fax.c b/res/res_fax.c
index 8695414eafb7605f32c4e2d90e4515a081941c09..5f2704110b3da1960d8f2b5f8ed85e2da0330bce 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -769,7 +769,6 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de
 	}
 
 	ast_channel_lock(chan);
-	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", status);
 	if (details->option.statusevents) {
 		struct manager_event_info info;
 
@@ -797,13 +796,28 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de
 	return 0;
 }
 
+/*! \brief Set fax related channel variables. */
+static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
+{
+	char buf[10];
+	pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
+	pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
+	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
+	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
+	pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
+	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
+
+	snprintf(buf, sizeof(buf), "%d", details->pages_transferred);
+	pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
+}
+
 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)	\
 	do {	\
 		ast_log(LOG_ERROR, "channel '%s' FAX session '%d' failure, reason: '%s' (%s)\n", chan->name, fax->id, reason, errorstr); \
-		pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", reason); \
-		if (ast_strlen_zero(fax->details->result)) ast_string_field_set(fax->details, result, "FAILED"); \
-		if (ast_strlen_zero(fax->details->resultstr)) ast_string_field_set(fax->details, resultstr, reason); \
-		if (ast_strlen_zero(fax->details->error)) ast_string_field_set(fax->details, error, errorstr); \
+		ast_string_field_set(fax->details, result, S_OR(fax->details->result, "FAILED")); \
+		ast_string_field_set(fax->details, resultstr, S_OR(fax->details->resultstr, reason)); \
+		ast_string_field_set(fax->details, error, S_OR(fax->details->error, errorstr)); \
+		set_channel_variables(chan, fax->details); \
 		res = ms = -1; \
 	} while (0)
 
@@ -934,7 +948,6 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
 	int res = 0, chancount;
 	unsigned int expected_frametype = -1;
 	union ast_frame_subclass expected_framesubclass = { .integer = -1 };
-	char tbuf[10];
 	unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
 	struct ast_control_t38_parameters t38_parameters;
 	const char *tempvar;
@@ -1009,13 +1022,12 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
 	ast_string_field_set(details, result, "");
 	ast_string_field_set(details, resultstr, "");
 	ast_string_field_set(details, error, "");
+	set_channel_variables(chan, details);
 
 	if (fax->tech->start_session(fax) < 0) {
 		GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
 	}
 
-	pbx_builtin_setvar_helper(chan, "FAXSTATUS", NULL);
-	pbx_builtin_setvar_helper(chan, "FAXERROR", NULL);
 	report_fax_status(chan, details, "FAX Transmission In Progress");
 
 	ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
@@ -1036,6 +1048,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
  				 * send the FAX stack silence so the modems can finish their session without
  				 * any problems */
 				ast_log(LOG_NOTICE, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
+				GENERIC_FAX_EXEC_ERROR(fax, chan, "HANGUP", "remote end hungup");
 				c = NULL;
 				chancount = 0;
 				timeout -= (1000 - ms);
@@ -1129,9 +1142,12 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
 			if (ms && (ofd < 0)) {
 				if ((errno == 0) || (errno == EINTR)) {
 					timeout -= (1000 - ms);
+					if (timeout <= 0)
+						GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
 					continue;
 				} else {
 					ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
+					GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
 					res = ms;
 					break;
 				}
@@ -1139,6 +1155,8 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
 				/* nothing happened */
 				if (timeout > 0) {
 					timeout -= 1000;
+					if (timeout <= 0)
+						GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
 					continue;
 				} else {
 					ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", chan->name);
@@ -1150,15 +1168,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
 	}
 	ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", chan->name, timeout, ms, res);
 
-	pbx_builtin_setvar_helper(chan, "FAXSTATUS", details->result);
-	pbx_builtin_setvar_helper(chan, "FAXERROR", details->error);
-	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", details->resultstr);
-	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", details->remotestationid);
-	pbx_builtin_setvar_helper(chan, "FAXBITRATE", details->transfer_rate);
-	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", details->resolution);
-
-	snprintf(tbuf, sizeof(tbuf), "%d", details->pages_transferred);
-	pbx_builtin_setvar_helper(chan, "FAXPAGES", tbuf);
+	set_channel_variables(chan, details);
 
 	ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
 	if (!strcasecmp(details->result, "FAILED")) {
@@ -1354,40 +1364,49 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 	struct ast_flags opts = { 0, };
 	struct manager_event_info info;
 
+	/* initialize output channel variables */
+	pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
+	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
+	pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
+	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
+	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
+
 	/* Get a FAX session details structure from the channel's FAX datastore and create one if
 	 * it does not already exist. */
 	if (!(details = find_or_create_details(chan))) {
+		pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
+		pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
 		return -1;
 	}
 
+	set_channel_variables(chan, details);
 
 	if (ast_strlen_zero(data)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
-	
-	/* initialize output channel variables */
-	pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
-	pbx_builtin_setvar_helper(chan, "FAXERROR", "Application Problems");
-	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Invalid application arguments.");
-	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
-	pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
-	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
-	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
 
 	if (!ast_strlen_zero(args.options) &&
 	    ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
+		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
+		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	if (ast_strlen_zero(args.filename)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1395,7 +1414,9 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 	if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	
@@ -1403,6 +1424,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 	if (chan->_state != AST_STATE_UP) {
 		if (ast_answer(chan)) {
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
+			ao2_ref(details, -1);
 			return -1;
 		}
 	}
@@ -1415,6 +1437,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 	if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
 		ast_string_field_set(details, error, "MEMORY_ERROR");
 		ast_string_field_set(details, resultstr, "error allocating memory");
+		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
 		ao2_ref(details, -1);
 		return -1;
@@ -1445,6 +1468,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 	if (set_fax_t38_caps(chan, details)) {
 		ast_string_field_set(details, error, "T38_NEG_ERROR");
 		ast_string_field_set(details, resultstr, "error negotiating T.38");
+		set_channel_variables(chan, details);
 		ao2_ref(details, -1);
 		return -1;
 	}
@@ -1453,6 +1477,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
 		if (receivefax_t38_init(chan, details)) {
 			ast_string_field_set(details, error, "T38_NEG_ERROR");
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
+			set_channel_variables(chan, details);
 			ao2_ref(details, -1);
 			ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
 			return -1;
@@ -1744,39 +1769,50 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 	struct ast_flags opts = { 0, };
 	struct manager_event_info info;
 
+	/* initialize output channel variables */
+	pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
+	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
+	pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
+	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
+	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
+
 	/* Get a requirement structure and set it.  This structure is used
 	 * to tell the FAX technology module about the higher level FAX session */
 	if (!(details = find_or_create_details(chan))) {
+		pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
+		pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
 		return -1;
 	}
 
+	set_channel_variables(chan, details);
+
 	if (ast_strlen_zero(data)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
 
-	/* initialize output channel variables */
-	pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
-	pbx_builtin_setvar_helper(chan, "FAXERROR", "Application Problems");
-	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Invalid application arguments.");
-	pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
-	pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
-	pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
-	pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
 
 	if (!ast_strlen_zero(args.options) &&
 	    ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
+		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
+		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	if (ast_strlen_zero(args.filenames)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 	
@@ -1784,7 +1820,9 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 	if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
+		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
+		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1792,14 +1830,12 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 	if (chan->_state != AST_STATE_UP) {
 		if (ast_answer(chan)) {
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
+			ao2_ref(details, -1);
 			return -1;
 		}
 	}
 
 	ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
-	
-	pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
-	pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
 
 	file_count = 0;
 	filenames = args.filenames;
@@ -1807,6 +1843,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 		if (access(c, (F_OK | R_OK)) < 0) {
 			ast_string_field_set(details, error, "FILE_ERROR");
 			ast_string_field_set(details, resultstr, "error reading file");
+			set_channel_variables(chan, details);
 			ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filenames);
 			ao2_ref(details, -1);
 			return -1;
@@ -1815,6 +1852,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 		if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
 			ast_string_field_set(details, error, "MEMORY_ERROR");
 			ast_string_field_set(details, resultstr, "error allocating memory");
+			set_channel_variables(chan, details);
 			ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
 			ao2_ref(details, -1);
 			return -1;
@@ -1858,6 +1896,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 	if (set_fax_t38_caps(chan, details)) {
 		ast_string_field_set(details, error, "T38_NEG_ERROR");
 		ast_string_field_set(details, resultstr, "error negotiating T.38");
+		set_channel_variables(chan, details);
 		ao2_ref(details, -1);
 		return -1;
 	}
@@ -1866,6 +1905,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
 		if (sendfax_t38_init(chan, details)) {
 			ast_string_field_set(details, error, "T38_NEG_ERROR");
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
+			set_channel_variables(chan, details);
 			ao2_ref(details, -1);
 			ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
 			return -1;