Tests: Add test to check shared-memory FD leaks after relayd dies
[lttng-tools.git] / src / bin / lttng-relayd / connection.cpp
CommitLineData
58eb9381 1/*
ab5be9fa
MJ
2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
58eb9381 5 *
ab5be9fa 6 * SPDX-License-Identifier: GPL-2.0-only
58eb9381 7 *
58eb9381
DG
8 */
9
6c1c0768 10#define _LGPL_SOURCE
c9e313bc
SM
11#include "connection.hpp"
12#include "stream.hpp"
13#include "viewer-session.hpp"
58eb9381 14
28ab034a 15#include <common/common.hpp>
56047f5a 16#include <common/urcu.hpp>
28ab034a
JG
17
18#include <urcu/rculist.h>
19
7591bab1 20bool connection_get(struct relay_connection *conn)
58eb9381 21{
ce4d4083 22 return urcu_ref_get_unless_zero(&conn->ref);
58eb9381
DG
23}
24
28ab034a 25struct relay_connection *connection_get_by_sock(struct lttng_ht *relay_connections_ht, int sock)
58eb9381
DG
26{
27 struct lttng_ht_node_ulong *node;
28 struct lttng_ht_iter iter;
cd9adb8b 29 struct relay_connection *conn = nullptr;
58eb9381 30
a0377dfe 31 LTTNG_ASSERT(sock >= 0);
58eb9381 32
56047f5a 33 lttng::urcu::read_lock_guard read_lock;
28ab034a 34 lttng_ht_lookup(relay_connections_ht, (void *) ((unsigned long) sock), &iter);
58eb9381
DG
35 node = lttng_ht_iter_get_node_ulong(&iter);
36 if (!node) {
37 DBG2("Relay connection by sock %d not found", sock);
38 goto end;
39 }
0114db0e 40 conn = lttng::utils::container_of(node, &relay_connection::sock_n);
7591bab1 41 if (!connection_get(conn)) {
cd9adb8b 42 conn = nullptr;
7591bab1 43 }
58eb9381
DG
44end:
45 return conn;
46}
47
5312a3ed
JG
48int connection_reset_protocol_state(struct relay_connection *connection)
49{
50 int ret = 0;
51
52 switch (connection->type) {
53 case RELAY_DATA:
28ab034a 54 connection->protocol.data.state_id = DATA_CONNECTION_STATE_RECEIVE_HEADER;
5312a3ed 55 memset(&connection->protocol.data.state.receive_header,
28ab034a
JG
56 0,
57 sizeof(connection->protocol.data.state.receive_header));
5312a3ed 58 connection->protocol.data.state.receive_header.left_to_receive =
28ab034a 59 sizeof(struct lttcomm_relayd_data_hdr);
5312a3ed
JG
60 break;
61 case RELAY_CONTROL:
28ab034a 62 connection->protocol.ctrl.state_id = CTRL_CONNECTION_STATE_RECEIVE_HEADER;
5312a3ed 63 memset(&connection->protocol.ctrl.state.receive_header,
28ab034a
JG
64 0,
65 sizeof(connection->protocol.ctrl.state.receive_header));
5312a3ed 66 connection->protocol.data.state.receive_header.left_to_receive =
28ab034a
JG
67 sizeof(struct lttcomm_relayd_hdr);
68 ret = lttng_dynamic_buffer_set_size(&connection->protocol.ctrl.reception_buffer,
69 sizeof(struct lttcomm_relayd_hdr));
5312a3ed 70 if (ret) {
28ab034a
JG
71 ERR("Failed to reinitialize control connection reception buffer size to %zu bytes.",
72 sizeof(struct lttcomm_relayd_hdr));
5312a3ed
JG
73 goto end;
74 }
75 break;
76 default:
77 goto end;
78 }
28ab034a 79 DBG("Reset communication state of relay connection (fd = %i)", connection->sock->fd);
5312a3ed
JG
80end:
81 return ret;
82}
83
28ab034a 84struct relay_connection *connection_create(struct lttcomm_sock *sock, enum connection_type type)
58eb9381 85{
7591bab1 86 struct relay_connection *conn;
58eb9381 87
64803277 88 conn = zmalloc<relay_connection>();
7591bab1
MD
89 if (!conn) {
90 PERROR("zmalloc relay connection");
91 goto end;
92 }
7591bab1
MD
93 urcu_ref_init(&conn->ref);
94 conn->type = type;
95 conn->sock = sock;
96 lttng_ht_node_init_ulong(&conn->sock_n, (unsigned long) conn->sock->fd);
5312a3ed
JG
97 if (conn->type == RELAY_CONTROL) {
98 lttng_dynamic_buffer_init(&conn->protocol.ctrl.reception_buffer);
99 }
100 connection_reset_protocol_state(conn);
7591bab1
MD
101end:
102 return conn;
58eb9381
DG
103}
104
7591bab1 105static void rcu_free_connection(struct rcu_head *head)
58eb9381 106{
7591bab1 107 struct relay_connection *conn =
0114db0e 108 lttng::utils::container_of(head, &relay_connection::rcu_node);
58eb9381 109
7591bab1
MD
110 lttcomm_destroy_sock(conn->sock);
111 if (conn->viewer_session) {
112 viewer_session_destroy(conn->viewer_session);
cd9adb8b 113 conn->viewer_session = nullptr;
7591bab1 114 }
35be817a 115 if (conn->type == RELAY_CONTROL) {
28ab034a 116 lttng_dynamic_buffer_reset(&conn->protocol.ctrl.reception_buffer);
35be817a 117 }
7591bab1
MD
118 free(conn);
119}
120
121static void destroy_connection(struct relay_connection *conn)
122{
58eb9381
DG
123 call_rcu(&conn->rcu_node, rcu_free_connection);
124}
125
7591bab1 126static void connection_release(struct urcu_ref *ref)
58eb9381 127{
28ab034a 128 struct relay_connection *conn = lttng::utils::container_of(ref, &relay_connection::ref);
58eb9381 129
7591bab1
MD
130 if (conn->in_socket_ht) {
131 struct lttng_ht_iter iter;
132 int ret;
133
134 iter.iter.node = &conn->sock_n.node;
135 ret = lttng_ht_del(conn->socket_ht, &iter);
a0377dfe 136 LTTNG_ASSERT(!ret);
58eb9381
DG
137 }
138
7591bab1
MD
139 if (conn->session) {
140 if (session_close(conn->session)) {
141 ERR("session_close");
142 }
cd9adb8b 143 conn->session = nullptr;
7591bab1
MD
144 }
145 if (conn->viewer_session) {
146 viewer_session_close(conn->viewer_session);
147 }
148 destroy_connection(conn);
58eb9381
DG
149}
150
7591bab1 151void connection_put(struct relay_connection *conn)
58eb9381 152{
56047f5a 153 lttng::urcu::read_lock_guard read_lock;
7591bab1 154 urcu_ref_put(&conn->ref, connection_release);
58eb9381
DG
155}
156
28ab034a 157void connection_ht_add(struct lttng_ht *relay_connections_ht, struct relay_connection *conn)
58eb9381 158{
a0377dfe 159 LTTNG_ASSERT(!conn->in_socket_ht);
7591bab1 160 lttng_ht_add_unique_ulong(relay_connections_ht, &conn->sock_n);
cd9adb8b 161 conn->in_socket_ht = true;
7591bab1 162 conn->socket_ht = relay_connections_ht;
58eb9381 163}
fd0f1e3e 164
28ab034a 165int connection_set_session(struct relay_connection *conn, struct relay_session *session)
fd0f1e3e
JR
166{
167 int ret = 0;
168
a0377dfe
FD
169 LTTNG_ASSERT(conn);
170 LTTNG_ASSERT(session);
171 LTTNG_ASSERT(!conn->session);
fd0f1e3e
JR
172
173 if (connection_get(conn)) {
174 if (session_get(session)) {
175 conn->session = session;
176 } else {
177 ERR("Failed to get session reference in connection_set_session()");
178 ret = -1;
179 }
180 connection_put(conn);
181 } else {
182 ERR("Failed to get connection reference in connection_set_session()");
183 ret = -1;
184 }
185 return ret;
186}
This page took 0.074027 seconds and 4 git commands to generate.