#include "health-sessiond.h"
#include "testpoint.h"
#include "ust-thread.h"
+#include "jul-thread.h"
#define CONSUMERD_FILE "lttng-consumerd"
static pthread_t dispatch_thread;
static pthread_t health_thread;
static pthread_t ht_cleanup_thread;
+static pthread_t jul_reg_thread;
/*
* UST registration command queue. This queue is tied with a futex and uses a N
/* Application health monitoring */
struct health_app *health_sessiond;
+/* JUL TCP port for registration. Used by the JUL thread. */
+unsigned int jul_tcp_port = DEFAULT_JUL_TCP_PORT;
+
static
void setup_consumerd_path(void)
{
DBG("Removing %s", path);
(void) unlink(path);
+ snprintf(path, PATH_MAX, "%s/%s", rundir,
+ DEFAULT_LTTNG_SESSIOND_JULPORT_FILE);
+ DBG("Removing %s", path);
+ (void) unlink(path);
+
/* kconsumerd */
snprintf(path, PATH_MAX,
DEFAULT_KCONSUMERD_ERR_SOCK_PATH,
DBG("Removing directory %s", path);
(void) rmdir(path);
+ /*
+ * We do NOT rmdir rundir because there are other processes
+ * using it, for instance lttng-relayd, which can start in
+ * parallel with this teardown.
+ */
+
free(rundir);
DBG("Cleaning up all sessions");
goto error;
}
- /*
- * Set socket timeout for both receiving and ending.
- * app_socket_timeout is in seconds, whereas
- * lttcomm_setsockopt_rcv_timeout and
- * lttcomm_setsockopt_snd_timeout expect msec as
- * parameter.
- */
- (void) lttcomm_setsockopt_rcv_timeout(sock,
- app_socket_timeout * 1000);
- (void) lttcomm_setsockopt_snd_timeout(sock,
- app_socket_timeout * 1000);
-
DBG("Apps with sock %d added to poll set", sock);
health_code_update();
if (ret < 0) {
PERROR("close ust sock dispatch %d", ust_cmd->sock);
}
- lttng_fd_put(1, LTTNG_FD_APPS);
+ lttng_fd_put(LTTNG_FD_APPS, 1);
free(ust_cmd);
goto error;
}
if (ret < 0) {
PERROR("close ust sock dispatch %d", ust_cmd->sock);
}
- lttng_fd_put(1, LTTNG_FD_APPS);
+ lttng_fd_put(LTTNG_FD_APPS, 1);
free(wait_node);
free(ust_cmd);
continue;
if (ret < 0) {
PERROR("close ust sock dispatch %d", ust_cmd->sock);
}
- lttng_fd_put(1, LTTNG_FD_APPS);
+ lttng_fd_put(LTTNG_FD_APPS, 1);
}
free(ust_cmd);
}
goto error;
}
+ /*
+ * Set socket timeout for both receiving and ending.
+ * app_socket_timeout is in seconds, whereas
+ * lttcomm_setsockopt_rcv_timeout and
+ * lttcomm_setsockopt_snd_timeout expect msec as
+ * parameter.
+ */
+ (void) lttcomm_setsockopt_rcv_timeout(sock,
+ app_socket_timeout * 1000);
+ (void) lttcomm_setsockopt_snd_timeout(sock,
+ app_socket_timeout * 1000);
+
/*
* Set the CLOEXEC flag. Return code is useless because
* either way, the show must go on.
consumer = session->kernel_session->consumer;
dir_name = DEFAULT_KERNEL_TRACE_DIR;
break;
+ case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_UST:
DBG3("Copying tracing session consumer output in UST session");
if (session->ust_session->consumer) {
assert(session->consumer);
switch (domain->type) {
+ case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_UST:
break;
default:
}
break;
+ case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_UST:
{
if (!ust_app_supported()) {
if (cmd_ctx->lsm->cmd_type == LTTNG_START_TRACE ||
cmd_ctx->lsm->cmd_type == LTTNG_STOP_TRACE) {
switch (cmd_ctx->lsm->domain.type) {
+ case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_UST:
if (uatomic_read(&ust_consumerd_state) != CONSUMER_STARTED) {
ret = LTTNG_ERR_NO_USTCONSUMERD;
fprintf(stderr, " -p, --pidfile FILE Write a pid to FILE name overriding the default value.\n");
fprintf(stderr, " --verbose-consumer Verbose mode for consumer. Activate DBG() macro.\n");
fprintf(stderr, " --no-kernel Disable kernel tracer\n");
+ fprintf(stderr, " --jul-tcp-port JUL application registration TCP port\n");
}
/*
{ "verbose-consumer", 0, 0, 'Z' },
{ "no-kernel", 0, 0, 'N' },
{ "pidfile", 1, 0, 'p' },
+ { "jul-tcp-port", 1, 0, 'J' },
{ NULL, 0, 0, 0 }
};
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhqvVSN" "a:c:g:s:C:E:D:F:Z:u:t:p:",
+ c = getopt_long(argc, argv, "dhqvVSN" "a:c:g:s:C:E:D:F:Z:u:t:p:J:",
long_options, &option_index);
if (c == -1) {
break;
case 'p':
opt_pidfile = optarg;
break;
+ case 'J': /* JUL TCP port. */
+ {
+ unsigned long v;
+
+ errno = 0;
+ v = strtoul(optarg, NULL, 0);
+ if (errno != 0 || !isdigit(optarg[0])) {
+ ERR("Wrong value in --jul-tcp-port parameter: %s", optarg);
+ return -1;
+ }
+ if (v == 0 || v >= 65535) {
+ ERR("Port overflow in --jul-tcp-port parameter: %s", optarg);
+ return -1;
+ }
+ jul_tcp_port = (uint32_t) v;
+ DBG3("JUL TCP port set to non default: %u", jul_tcp_port);
+ break;
+ }
default:
/* Unknown option or other error.
* Error is printed by getopt, just return */
return;
}
+/*
+ * Write JUL TCP port using the rundir.
+ */
+static void write_julport(void)
+{
+ int ret;
+ char path[PATH_MAX];
+
+ assert(rundir);
+
+ ret = snprintf(path, sizeof(path), "%s/"
+ DEFAULT_LTTNG_SESSIOND_JULPORT_FILE, rundir);
+ if (ret < 0) {
+ PERROR("snprintf julport path");
+ goto error;
+ }
+
+ /*
+ * Create TCP JUL port file in rundir. Return value is of no importance.
+ * The execution will continue even though we are not able to write the
+ * file.
+ */
+ (void) utils_create_pid_file(jul_tcp_port, path);
+
+error:
+ return;
+}
+
/*
* main
*/
*/
ust_app_ht_alloc();
+ /* Initialize JUL domain subsystem. */
+ if ((ret = jul_init()) < 0) {
+ /* ENOMEM at this point. */
+ goto error;
+ }
+
/* After this point, we can safely call cleanup() with "goto exit" */
/*
}
write_pidfile();
+ write_julport();
/* Initialize communication library */
lttcomm_init();
goto exit_apps_notify;
}
+ /* Create JUL registration thread. */
+ ret = pthread_create(&jul_reg_thread, NULL,
+ jul_thread_manage_registration, (void *) NULL);
+ if (ret != 0) {
+ PERROR("pthread_create apps");
+ goto exit_jul_reg;
+ }
+
/* Don't start this thread if kernel tracing is not requested nor root */
if (is_root && !opt_no_kernel) {
/* Create kernel thread to manage kernel event */
}
exit_kernel:
+ ret = pthread_join(jul_reg_thread, &status);
+ if (ret != 0) {
+ PERROR("pthread_join JUL");
+ goto error; /* join error, exit without cleanup */
+ }
+
+exit_jul_reg:
ret = pthread_join(apps_notify_thread, &status);
if (ret != 0) {
PERROR("pthread_join apps notify");