mod_netconf: connect/close, locking
diff --git a/src/mod_netconf.c b/src/mod_netconf.c
index d5ae61b..1bc0390 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -301,6 +301,7 @@
 		locked_session->session = session;
 		locked_session->last_activity = apr_time_now();
 		locked_session->hello_message = NULL;
+		locked_session->closed = 0;
 		pthread_mutex_init (&locked_session->lock, NULL);
 		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "Before session_lock");
 		/* get exclusive access to sessions_list (conns) */
@@ -338,15 +339,50 @@
 	struct nc_session *ns = NULL;
 	struct session_with_mutex * locked_session;
 
-	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Key in hash to get: %s", session_key);
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Key in hash to close: %s", session_key);
 	/* get exclusive (write) access to sessions_list (conns) */
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock session lock.");
 	if (pthread_rwlock_wrlock (&session_lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
 		return EXIT_FAILURE;
 	}
 	locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
 	if (locked_session != NULL) {
 		/** \todo free all notifications from queue */
+		ns = locked_session->session;
+	}
+	if (ns != NULL) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock private lock.");
+		if (pthread_mutex_lock(&locked_session->lock) != 0) {
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		locked_session->ntfc_subscribed = 0;
+		locked_session->closed = 1;
+		nc_session_close (ns, NC_SESSION_TERM_CLOSED);
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "session closed.");
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock private lock.");
+		if (pthread_mutex_unlock(&locked_session->lock) != 0) {
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "closed session, disabled notif(?), wait 2s");
+		sleep(2); /* let notification thread stop */
+		/* remove session from the active sessions list */
+		apr_hash_set(conns, session_key, APR_HASH_KEY_STRING, NULL);
+		/* end of critical section */
+
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "lock session lock.");
+		if (pthread_rwlock_wrlock (&session_lock) != 0) {
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+			return EXIT_FAILURE;
+		}
+		/** \todo free all notifications from queue */
 		apr_array_clear(locked_session->notifications);
 		pthread_mutex_destroy(&locked_session->lock);
 		ns = locked_session->session;
@@ -354,26 +390,21 @@
 			json_object_put(locked_session->hello_message);
 			locked_session->hello_message = NULL;
 		}
-		free (locked_session);
-	}
-	if (ns != NULL) {
-		nc_session_close (ns, NC_SESSION_TERM_CLOSED);
-		nc_session_free (ns);
+		nc_session_free(ns);
 		ns = NULL;
-
-		/* remove session from the active sessions list */
-		apr_hash_set(conns, session_key, APR_HASH_KEY_STRING, NULL);
-		/* end of critical section */
+		free (locked_session);
+		locked_session = NULL;
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
 		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 			return EXIT_FAILURE;
 		}
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "NETCONF session closed");
-
+		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "NETCONF session closed, everything cleared.");
 		return (EXIT_SUCCESS);
 	} else {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "unlock session lock.");
 		if (pthread_rwlock_unlock (&session_lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
 			return EXIT_FAILURE;
 		}
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to close");
@@ -1417,11 +1448,10 @@
 			operation = json_object_get_int(json_object_object_get(request, "type"));
 
 			session_key = json_object_get_string(json_object_object_get(request, "session"));
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "operation %d session_key %s.", operation, session_key);
 			/* DO NOT FREE session_key HERE, IT IS PART OF REQUEST */
 			if (operation != MSG_CONNECT && session_key == NULL) {
-				reply =  json_object_new_object();
-				json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
-				json_object_object_add(reply, "error-message", json_object_new_string("Missing session specification."));
+				reply = create_error("Missing session specification.");
 				msgtext = json_object_to_json_string(reply);
 				send(client, msgtext, strlen(msgtext) + 1, 0);
 				json_object_put(reply);
@@ -1575,7 +1605,13 @@
 	struct nc_session *ns = NULL;
 	const char *hashed_key = NULL;
 	apr_ssize_t hashed_key_length;
+	int ret;
 
+	/* get exclusive access to sessions_list (conns) */
+	if ((ret = pthread_rwlock_wrlock (&session_lock)) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", ret, strerror(ret));
+		return;
+	}
 	for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
 		apr_hash_this(hi, (const void **) &hashed_key, &hashed_key_length, &val);
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Closing NETCONF session (%s).", hashed_key);
@@ -1591,6 +1627,10 @@
 			pthread_mutex_unlock(&swm->lock);
 		}
 	}
+	/* get exclusive access to sessions_list (conns) */
+	if (pthread_rwlock_unlock (&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+	}
 }
 
 static void check_timeout_and_close(server_rec* server, apr_pool_t *p, apr_hash_t *ht)
@@ -1602,7 +1642,13 @@
 	const char *hashed_key = NULL;
 	apr_ssize_t hashed_key_length;
 	apr_time_t current_time = apr_time_now();
+	int ret;
 
+	/* get exclusive access to sessions_list (conns) */
+	if ((ret = pthread_rwlock_wrlock (&session_lock)) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while locking rwlock: %d (%s)", ret, strerror(ret));
+		return;
+	}
 	for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
 		apr_hash_this(hi, (const void **) &hashed_key, &hashed_key_length, &val);
 		swm = (struct session_with_mutex *) val;
@@ -1624,6 +1670,10 @@
 		}
 		pthread_mutex_unlock(&swm->lock);
 	}
+	/* get exclusive access to sessions_list (conns) */
+	if (pthread_rwlock_unlock (&session_lock) != 0) {
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+	}
 }
 
 
diff --git a/src/mod_netconf.h b/src/mod_netconf.h
index 457de3c..b375403 100644
--- a/src/mod_netconf.h
+++ b/src/mod_netconf.h
@@ -70,6 +70,7 @@
 	apr_array_header_t *notifications;
 	json_object *hello_message;
 	char ntfc_subscribed; /**< 0 when notifications are not subscribed */
+	char closed;; /**< 0 when session is terminated */
 	apr_time_t last_activity;
 	pthread_mutex_t lock; /**< mutex protecting the session from multiple access */
 };
diff --git a/src/notification-server.c b/src/notification-server.c
index 1f2f7f2..13648ba 100644
--- a/src/notification-server.c
+++ b/src/notification-server.c
@@ -366,19 +366,7 @@
 	if (session_key == NULL) {
 		return (NULL);
 	}
-	if (pthread_rwlock_wrlock(&session_lock) != 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-		#endif
-		return (NULL);
-	}
 	locked_session = (struct session_with_mutex *)apr_hash_get(netconf_locked_sessions, session_key, APR_HASH_KEY_STRING);
-	if (pthread_rwlock_unlock (&session_lock) != 0) {
-		#ifndef TEST_NOTIFICATION_SERVER
-		ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-		#endif
-		return (NULL);
-	}
 	return locked_session;
 }
 
@@ -470,17 +458,28 @@
 	notification_t *ntf = NULL;
 	char *session_hash = NULL;
 
-	if (http_server != NULL) {
-		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "Accepted notif: %lu %s\n", (unsigned long int) eventtime, content);
-	}
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Accepted notif: %lu %s\n", (unsigned long int) eventtime, content);
 
 	session_hash = pthread_getspecific(thread_key);
 	if (http_server != NULL) {
 		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: fileprint getspecific (%s)", session_hash);
 	}
+	if (pthread_rwlock_wrlock(&session_lock) != 0) {
+		#ifndef TEST_NOTIFICATION_SERVER
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+		#endif
+		return;
+	}
+	ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Get session with mutex from key %s.", session_hash);
 	target_session = get_ncsession_from_key(session_hash);
 	if (target_session == NULL) {
 		ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "no session found last_session_key (%s)", session_hash);
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+#ifndef TEST_NOTIFICATION_SERVER
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+#endif
+			return;
+		}
 		return;
 	}
 
@@ -506,7 +505,13 @@
 	if (ntf == NULL) {
 		ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Failed to allocate element ");
 		if (pthread_mutex_unlock(&target_session->lock) != 0) {
-			ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			return;
+		}
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+#ifndef TEST_NOTIFICATION_SERVER
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+#endif
 			return;
 		}
 		return;
@@ -519,7 +524,19 @@
 	}
 
 	if (pthread_mutex_unlock(&target_session->lock) != 0) {
-		ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		if (pthread_rwlock_unlock (&session_lock) != 0) {
+			#ifndef TEST_NOTIFICATION_SERVER
+			ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+			#endif
+			return;
+		}
+		return;
+	}
+	if (pthread_rwlock_unlock (&session_lock) != 0) {
+		#ifndef TEST_NOTIFICATION_SERVER
+		ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+		#endif
 		return;
 	}
 }
@@ -764,39 +781,66 @@
 			session_key_buf[40] = '\0';
 			pss->session_key = strdup(session_key_buf);
 			sscanf(in+40, "%d %d", (int *) &start, (int *) &stop);
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: get key (%s) from (%s) (%i,%i)", pss->session_key, (char *) in, (int) start, (int) stop);
-			}
+			ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: get key (%s) from (%s) (%i,%i)", pss->session_key, (char *) in, (int) start, (int) stop);
 
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "lock session lock");
+			if (pthread_rwlock_rdlock (&session_lock) != 0) {
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+				return -1;
+			}
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "get session from key (%s)", pss->session_key);
 			struct session_with_mutex *ls = get_ncsession_from_key(pss->session_key);
 			if (ls == NULL) {
 				if (http_server != NULL) {
-					ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: session_key not found (%s)", pss->session_key);
+					ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: session_key not found (%s)", pss->session_key);
 				}
-				return 0;
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
+				if (pthread_rwlock_unlock (&session_lock) != 0) {
+					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+					return -1;
+				}
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Close notification client");
+				return -1;
+			}
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Found session to subscribe notif.");
+			if (ls->closed == 1) {
+				ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "session already closed - handle no notification");
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
+				if (pthread_rwlock_unlock (&session_lock) != 0) {
+					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+					return -1;
+				}
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Close notification client");
+				return -1;
 			}
 			if (ls->ntfc_subscribed != 0) {
-				ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: already subscribed");
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: already subscribed");
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
+				if (pthread_rwlock_unlock (&session_lock) != 0) {
+					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+					return -1;
+				}
+				/* do not close client, only do not subscribe again */
 				return 0;
 			}
-			if (http_server != NULL) {
-				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: prepare to subscribe stream");
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: prepare to subscribe stream");
+			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "unlock session lock");
+			if (pthread_rwlock_unlock (&session_lock) != 0) {
+				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+				return -1;
 			}
-
 			//if (pthread_rwlock_rdlock (&session_lock) != 0) {
 			//	ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
-			//	return EXIT_FAILURE;
+			//	return -1;
 			//}
-			notif_subscribe(ls, pss->session_key, (time_t) start, (time_t) stop);
+			return notif_subscribe(ls, pss->session_key, (time_t) start, (time_t) stop);
 			//if (pthread_rwlock_unlock (&session_lock) != 0) {
 			//	ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
-			//	return EXIT_FAILURE;
+			//	return -1;
 			//}
 		}
 		if (len < 6)
 			break;
-		if (strcmp((const char *)in, "reset\n") == 0)
-			pss->number = 0;
 		break;
 	/*
 	 * this just demonstrates how to use the protocol filter. If you won't