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));
+ }
}