#include "stream.h"
#include "connection.h"
#include "tracefile-array.h"
+#include "tcp_keep_alive.h"
+
+static const char *help_msg =
+#ifdef LTTNG_EMBED_HELP
+#include <lttng-relayd.8.h>
+#else
+NULL
+#endif
+;
/* command line options */
char *opt_output_path;
static int opt_daemon, opt_background;
+static int opt_allow_clear = 1;
/*
* We need to wait for listener and live listener threads, as well as
{ "verbose", 0, 0, 'v', },
{ "config", 1, 0, 'f' },
{ "version", 0, 0, 'V' },
+ { "disallow-clear", 0, 0, 'x' },
{ NULL, 0, 0, 0, },
};
}
break;
case 'h':
- ret = utils_show_man_page(8, "lttng-relayd");
+ ret = utils_show_help(8, "lttng-relayd", help_msg);
if (ret) {
- ERR("Cannot view man page lttng-relayd(8)");
+ ERR("Cannot show --help for `lttng-relayd`");
perror("exec");
}
exit(EXIT_FAILURE);
}
}
break;
+ case 'x':
+ /* Disallow clear */
+ opt_allow_clear = 0;
+ break;
default:
/* Unknown option or other error.
* Error is printed by getopt, just return */
int orig_optopt = optopt, orig_optind = optind;
char *default_address, *optstring;
const char *config_path = NULL;
+ const char *value = NULL;
optstring = utils_generate_optstring(long_options,
sizeof(long_options) / sizeof(struct option));
}
}
+ if (opt_allow_clear) {
+ /* Check if env variable exists. */
+ value = lttng_secure_getenv(DEFAULT_LTTNG_RELAYD_DISALLOW_CLEAR_ENV);
+ if (value) {
+ ret = config_parse_value(value);
+ if (ret < 0) {
+ ERR("Invalid value for %s specified", DEFAULT_LTTNG_RELAYD_DISALLOW_CLEAR_ENV);
+ retval = -1;
+ goto exit;
+ }
+ opt_allow_clear = !ret;
+ }
+ }
+
exit:
free(optstring);
return retval;
ret = sock->ops->bind(sock);
if (ret < 0) {
+ PERROR("Failed to bind socket");
goto error;
}
lttcomm_destroy_sock(newsock);
goto error;
}
+
+ ret = socket_apply_keep_alive_config(newsock->fd);
+ if (ret < 0) {
+ ERR("Failed to apply TCP keep-alive configuration on socket (%i)",
+ newsock->fd);
+ lttcomm_destroy_sock(newsock);
+ goto error;
+ }
+
new_conn = connection_create(newsock, type);
if (!new_conn) {
lttcomm_destroy_sock(newsock);
health_code_update();
- while (!CMM_LOAD_SHARED(dispatch_thread_exit)) {
+ for (;;) {
health_code_update();
/* Atomically prepare the queue futex */
futex_nto1_prepare(&relay_conn_queue.futex);
+ if (CMM_LOAD_SHARED(dispatch_thread_exit)) {
+ break;
+ }
+
do {
health_code_update();
{
int ret;
struct lttcomm_relayd_version reply, msg;
+ bool compatible = true;
conn->version_check_done = 1;
if (reply.major != be32toh(msg.major)) {
DBG("Incompatible major versions (%u vs %u), deleting session",
reply.major, be32toh(msg.major));
- connection_put(conn);
- ret = 0;
- goto end;
+ compatible = false;
}
conn->major = reply.major;
ERR("Relay sending version");
}
+ if (!compatible) {
+ ret = -1;
+ goto end;
+ }
+
DBG("Version check done using protocol %u.%u", conn->major,
conn->minor);
/* no flush. */
ret = 0;
} else {
+ /*
+ * ret < 0
+ *
+ * relay_index_try_flush is responsible for the self-reference
+ * put of the index object on error.
+ */
ERR("relay_index_try_flush error %d", ret);
- relay_index_put(index);
ret = -1;
}
/* No flush. */
ret = 0;
} else {
- /* Put self-ref for this index due to error. */
- relay_index_put(index);
- index = NULL;
+ /*
+ * ret < 0
+ *
+ * relay_index_try_flush is responsible for the self-reference
+ * put of the index object on error.
+ */
+ ERR("relay_index_try_flush error %d", ret);
ret = -1;
}
end:
destroy_conn,
sock_n.node) {
health_code_update();
+
+ if (session_abort(destroy_conn->session)) {
+ assert(0);
+ }
+
/*
* No need to grab another ref, because we own
* destroy_conn.
goto exit_options;
}
+ if (!opt_allow_clear) {
+ DBG("Clear command disallowed.");
+ }
+
/* Try to create directory if -o, --output is specified. */
if (opt_output_path) {
if (*opt_output_path != '/') {
health_app_destroy(health_relayd);
exit_health_app_create:
exit_options:
+ /*
+ * Wait for all pending call_rcu work to complete before tearing
+ * down data structures. call_rcu worker may be trying to
+ * perform lookups in those structures.
+ */
+ rcu_barrier();
relayd_cleanup();
/* Ensure all prior call_rcu are done. */