* This unlinks the ari_ws_session from the registry and cleans up the
* decrements the reference count.
*/
-static void session_cleanup(struct ari_ws_session *session)
+static void session_cleanup(void *obj)
{
+ struct ari_ws_session *session = obj;
+ enum ast_websocket_type wstype;
+
if (!session) {
return;
}
- ast_debug(3, "%s: Cleaning up ARI websocket session RC: %d\n",
- session->session_id, (int)ao2_ref(session, 0));
+
+ /*
+ * We need to save the websocket type because client-per-call websockets
+ * will get destroyed when they're unlinked from the session_registry
+ * so we won't be able to test it afterwards.
+ */
+ wstype = session->type;
+
+ ast_debug(3, "%s: Cleaning up ARI %s websocket session. Refcount: %d\n",
+ session->session_id, ast_websocket_type_to_str(wstype), (int)ao2_ref(session, 0));
session_reset(session);
if (session_registry) {
- ast_debug(3, "%s: Unlinking websocket session from registry RC: %d\n",
- session->session_id, (int)ao2_ref(session, 0));
+ ast_debug(3, "%s: Unlinking %s websocket session from registry Refcount: %d\n",
+ session->session_id, ast_websocket_type_to_str(wstype), (int)ao2_ref(session, 0));
ao2_unlink(session_registry, session);
}
* was held by the registry container so we don't need
* to unref it here.
*/
- if (session->type != AST_WS_TYPE_CLIENT_PER_CALL_CONFIG) {
+ if (wstype != AST_WS_TYPE_CLIENT_PER_CALL_CONFIG) {
session_unref(session);
}
}
session->closing = 1;
session_cleanup(session);
if (session->ast_ws_session) {
+ ast_debug(3, "%s: Closing websocket\n", session->session_id);
ast_websocket_close(session->ast_ws_session, 1000);
+ } else if (session->thread) {
+ ast_debug(3, "%s: Cancelling handler thread\n", session->session_id);
+ pthread_cancel(session->thread);
}
return 0;
*/
static void *outbound_session_handler_thread(void *obj)
{
- RAII_VAR(struct ari_ws_session *, session, obj, session_cleanup);
+ struct ari_ws_session *session = obj;
int already_sent_registers = 1;
+ /*
+ * We use pthread_cleanup_push because RAII destructors don't run
+ * if we cancel the thread.
+ */
+ pthread_cleanup_push(session_cleanup, obj);
+
ast_debug(3, "%s: Starting outbound websocket thread RC: %d\n",
session->session_id, (int)ao2_ref(session, 0));
session->thread = pthread_self();
break;
}
+
+ if (session->closing) {
+ ast_debug(3, "%s: Websocket closing RC: %d\n",
+ session->session_id, (int)ao2_ref(session, 0));
+ break;
+ }
+
usleep(session->owc->websocket_client->reconnect_interval * 1000);
continue;
}
if (!upgrade_headers) {
ast_log(LOG_WARNING, "%s: Failed to create upgrade header\n", session->session_id);
session->thread = 0;
+ session->connected = 0;
ast_websocket_close(astws, 1000);
- return NULL;
+ session->ast_ws_session = NULL;
+ break;
}
session->connected = 1;
session->session_id, (int)ao2_ref(session, 0));
session->thread = 0;
+ pthread_cleanup_pop(1);
+
return NULL;
}
session->closing = 1;
session_cleanup(session);
if (session->ast_ws_session) {
+ ast_debug(3, "%s: Closing websocket\n", session->session_id);
ast_websocket_close(session->ast_ws_session, 1000);
+ } else if (session->thread) {
+ ast_debug(3, "%s: Cancelling handler thread\n", session->session_id);
+ pthread_cancel(session->thread);
}
if (session->type == AST_WS_TYPE_CLIENT_PERSISTENT) {