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