BUGFIX: segfault on error during subscribe, fixed deadlock
diff --git a/src/mod_netconf.c b/src/mod_netconf.c
index 8bc2435..2abc8b0 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -120,29 +120,7 @@
 
 static pthread_key_t notif_history_key;
 
-static pthread_key_t err_reply_key;
-
-#define GETSPEC_ERR_REPLY json_object *err_reply = *((json_object **) pthread_getspecific(err_reply_key));
-
-#define CHECK_ERR_SET_REPLY \
-if (reply == NULL) { \
-	GETSPEC_ERR_REPLY \
-	if (err_reply != NULL) { \
-		/* use filled err_reply from libnetconf's callback */ \
-		reply = err_reply; \
-	} \
-}
-
-#define CHECK_ERR_SET_REPLY_ERR(errmsg) \
-if (reply == NULL) { \
-	GETSPEC_ERR_REPLY \
-	if (err_reply == NULL) { \
-		reply = create_error(errmsg); \
-	} else { \
-		/* use filled err_reply from libnetconf's callback */ \
-		reply = err_reply; \
-	} \
-}
+pthread_key_t err_reply_key;
 
 volatile int isterminated = 0;
 
@@ -229,6 +207,10 @@
 		const char* sid)
 {
 	json_object **err_reply_p = (json_object **) pthread_getspecific(err_reply_key);
+	if (err_reply_p == NULL) {
+		DEBUG("Error message was not allocated. %s", __func__);
+		return;
+	}
 	json_object *err_reply = *err_reply_p;
 
 	json_object *array = NULL;
@@ -321,6 +303,49 @@
 
 }
 
+void create_err_reply_p()
+{
+	json_object **err_reply = calloc(1, sizeof(json_object **));
+	if (err_reply == NULL) {
+		DEBUG("Allocation of err_reply storage failed!");
+		return;
+	}
+	if (pthread_setspecific(err_reply_key, err_reply) != 0) {
+		DEBUG("cannot set thread-specific value.");
+	}
+}
+
+void clean_err_reply()
+{
+	json_object **err_reply = (json_object **) pthread_getspecific(err_reply_key);
+	if (err_reply != NULL) {
+		if (*err_reply != NULL) {
+			pthread_mutex_lock(&json_lock);
+			json_object_put(*err_reply);
+			pthread_mutex_unlock(&json_lock);
+		}
+		if (pthread_setspecific(err_reply_key, err_reply) != 0) {
+			DEBUG("Cannot set thread-specific hash value.");
+		}
+	}
+}
+
+void free_err_reply()
+{
+	json_object **err_reply = (json_object **) pthread_getspecific(err_reply_key);
+	if (err_reply != NULL) {
+		if (*err_reply != NULL) {
+			pthread_mutex_lock(&json_lock);
+			json_object_put(*err_reply);
+			pthread_mutex_unlock(&json_lock);
+		}
+		free(err_reply);
+		err_reply = NULL;
+		if (pthread_setspecific(err_reply_key, err_reply) != 0) {
+			DEBUG("Cannot set thread-specific hash value.");
+		}
+	}
+}
 
 /**
  * \defgroup netconf_operations NETCONF operations
@@ -1751,14 +1776,8 @@
 	char *buffer = NULL;
 
 	/* init thread specific err_reply memory */
-	json_object **err_reply = calloc(1, sizeof(json_object **));
-	if (err_reply == NULL) {
-		DEBUG("Allocation of err_reply storage failed!");
-		isterminated = 1;
-	}
-	if (pthread_setspecific(err_reply_key, err_reply) != 0) {
-		DEBUG("notif_history: cannot set thread-specific hash value.");
-	}
+	create_err_reply_p();
+
 	while (!isterminated) {
 		fds.fd = client;
 		fds.events = POLLIN;
@@ -1829,7 +1848,7 @@
 			}
 
 			/* null global JSON error-reply */
-			(*err_reply) = NULL;
+			clean_err_reply();
 
 			/* prepare reply envelope */
 			if (reply != NULL) {
@@ -1895,17 +1914,12 @@
 					break;
 				}
 
+				CHECK_ERR_SET_REPLY
 				if (reply == NULL) {
-					if (*err_reply == NULL) {
-						/** \todo more clever error message wanted */
-						pthread_mutex_lock(&json_lock);
-						reply = json_object_new_object();
-						json_object_object_add(reply, "type", json_object_new_int(REPLY_OK));
-						pthread_mutex_unlock(&json_lock);
-					} else {
-						/* use filled err_reply from libnetconf's callback */
-						reply = *err_reply;
-					}
+					pthread_mutex_lock(&json_lock);
+					reply = json_object_new_object();
+					json_object_object_add(reply, "type", json_object_new_int(REPLY_OK));
+					pthread_mutex_unlock(&json_lock);
 				}
 				break;
 			case MSG_KILL:
@@ -1963,35 +1977,18 @@
 					free(buffer);
 					buffer = NULL;
 				}
-				if ((err_reply != NULL) && (*err_reply != NULL)) {
-					json_object_put(*err_reply);
-					*err_reply = NULL;
-				}
 				pthread_mutex_unlock(&json_lock);
+				clean_err_reply();
 			} else {
 				pthread_mutex_unlock(&json_lock);
 				DEBUG("Reply is NULL, shouldn't be...");
-				if (*err_reply == NULL) {
-					DEBUG("No error was set - really strange situation");
-				} else {
-					DEBUG("Error was set but it was not sent.");
-				}
 				continue;
 			}
 		}
 	}
 	free (arg);
 
-	err_reply = (json_object **) pthread_getspecific(err_reply_key);
-	if (err_reply != NULL) {
-		if (*err_reply != NULL) {
-			pthread_mutex_lock(&json_lock);
-			json_object_put(*err_reply);
-			pthread_mutex_unlock(&json_lock);
-		}
-		free(err_reply);
-		err_reply = NULL;
-	}
+	free_err_reply();
 
 	return retval;
 }