* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* This file contains the implementation of the UST listener thread, which
+ * receives trace control commands. It also coordinates the initialization of
+ * libust.
+ */
+
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <urcu/uatomic_arch.h>
#include <ust/marker.h>
+#include <ust/tracepoint.h>
#include <ust/tracectl.h>
#include "tracer.h"
#include "usterr.h"
unlock_markers();
}
+static void print_trace_events(FILE *fp)
+{
+ struct trace_event_iter iter;
+
+ lock_trace_events();
+ trace_event_iter_reset(&iter);
+ trace_event_iter_start(&iter);
+
+ while(iter.trace_event) {
+ fprintf(fp, "trace_event: %s\n", iter.trace_event->name);
+ trace_event_iter_next(&iter);
+ }
+ unlock_trace_events();
+}
+
static int init_socket(void);
/* Ask the daemon to collect a trace called trace_name and being
/* iterate on all cpus */
for(j=0; j<trace->channels[i].n_cpus; j++) {
char *buf;
- asprintf(&buf, "%s_%d", trace->channels[i].channel_name, j);
+ if (asprintf(&buf, "%s_%d", trace->channels[i].channel_name, j) < 0) {
+ ERR("inform_consumer_daemon : asprintf failed (%s_%d)",
+ trace->channels[i].channel_name, j);
+ goto finish;
+ }
result = ustcomm_request_consumer(pid, buf);
if(result == -1) {
WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
else if(result < 0) {
ERR("ust_buffers_get_subbuf: error: %s", strerror(-result));
}
- asprintf(&reply, "%s %ld", "OK", consumed_old);
+ if (asprintf(&reply, "%s %ld", "OK", consumed_old) < 0) {
+ ERR("process_blkd_consumer_act : asprintf failed (OK %ld)",
+ consumed_old);
+ return -1;
+ }
result = ustcomm_send_reply(&bc->server, reply, &bc->src);
if(result < 0) {
ERR("ustcomm_send_reply failed");
*cpu = atoi(sep+1);
}
- asprintf(channel, "%.*s", (int)(sep-channel_and_cpu), channel_and_cpu);
+ if (asprintf(channel, "%.*s", (int)(sep-channel_and_cpu), channel_and_cpu) < 0) {
+ ERR("seperate_channel_cpu : asprintf failed (%.*s)",
+ (int)(sep-channel_and_cpu), channel_and_cpu);
+ return;
+ }
}
static int do_cmd_get_shmid(const char *recvbuf, struct ustcomm_source *src)
channel_and_cpu = nth_token(recvbuf, 1);
if(channel_and_cpu == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
if(ch_cpu == -1) {
ERR("problem parsing channel name");
+ retval = -1;
goto free_short_chan_name;
}
// DBG("the shmid for the requested channel is %d", buf->shmid);
// DBG("the shmid for its buffer structure is %d", channel->buf_struct_shmids);
- asprintf(&reply, "%d %d", buf->shmid, channel->buf_struct_shmids[ch_cpu]);
+ if (asprintf(&reply, "%d %d", buf->shmid, channel->buf_struct_shmids[ch_cpu]) < 0) {
+ ERR("do_cmd_get_shmid : asprintf failed (%d %d)",
+ buf->shmid, channel->buf_struct_shmids[ch_cpu]);
+ retval = -1;
+ goto free_short_chan_name;
+ }
result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
if(result) {
channel_and_cpu = nth_token(recvbuf, 1);
if(channel_and_cpu == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
if(ch_cpu == -1) {
ERR("problem parsing channel name");
+ retval = -1;
goto free_short_chan_name;
}
char *reply;
DBG("the n_subbufs for the requested channel is %d", channel->subbuf_cnt);
- asprintf(&reply, "%d", channel->subbuf_cnt);
+ if (asprintf(&reply, "%d", channel->subbuf_cnt) < 0) {
+ ERR("do_cmd_get_n_subbufs : asprintf failed (%d)",
+ channel->subbuf_cnt);
+ retval = -1;
+ goto free_short_chan_name;
+ }
result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
if(result) {
channel_and_cpu = nth_token(recvbuf, 1);
if(channel_and_cpu == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
if(ch_cpu == -1) {
ERR("problem parsing channel name");
+ retval = -1;
goto free_short_chan_name;
}
char *reply;
DBG("the subbuf_size for the requested channel is %zd", channel->subbuf_size);
- asprintf(&reply, "%zd", channel->subbuf_size);
+ if (asprintf(&reply, "%zd", channel->subbuf_size) < 0) {
+ ERR("do_cmd_get_subbuf_size : asprintf failed (%zd)",
+ channel->subbuf_size);
+ retval = -1;
+ goto free_short_chan_name;
+ }
result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
if(result) {
static unsigned int pow2_higher_or_eq(unsigned int v)
{
int hb = fls(v);
- int hbm1 = hb-1;
int retval = 1<<(hb-1);
if(v-retval == 0)
if(ch_name == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
if(ch_name == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
if (num < 2) {
ERR("subbuffer count should be greater than 2");
+ retval = -1;
goto end;
}
channel_and_cpu = nth_token(recvbuf, 1);
if(channel_and_cpu == NULL) {
ERR("cannot parse channel");
+ retval = -1;
goto end;
}
seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
if(ch_cpu == -1) {
ERR("problem parsing channel name");
+ retval = -1;
goto free_short_chan_name;
}
found = 1;
- bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
+ bc = (struct blocked_consumer *) zmalloc(sizeof(struct blocked_consumer));
if(bc == NULL) {
- ERR("malloc returned NULL");
+ ERR("zmalloc returned NULL");
goto unlock_traces;
}
bc->fd_consumer = src->fd;
result = ust_buffers_put_subbuf(buf, consumed_old);
if(result < 0) {
WARN("ust_buffers_put_subbuf: error (subbuf=%s)", channel_and_cpu);
- asprintf(&reply, "%s", "ERROR");
+ if (asprintf(&reply, "%s", "ERROR") < 0) {
+ ERR("do_cmd_put_subbuffer : asprintf failed (ERROR)");
+ retval = -1;
+ goto unlock_traces;
+ }
}
else {
DBG("ust_buffers_put_subbuf: success (subbuf=%s)", channel_and_cpu);
- asprintf(&reply, "%s", "OK");
+ if (asprintf(&reply, "%s", "OK") < 0) {
+ ERR("do_cmd_put_subbuffer : asprintf failed (OK)");
+ retval = -1;
+ goto unlock_traces;
+ }
}
result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
ustcomm_fini_app(&ustcomm_app, 0);
}
+static void do_cmd_force_switch()
+{
+ struct blocked_consumer *bc;
+
+ list_for_each_entry(bc, &blocked_consumers, list) {
+ ltt_force_switch(bc->buf, FORCE_FLUSH);
+ }
+}
+
int process_client_cmd(char *recvbuf, struct ustcomm_source *src)
{
int result;
result = ustcomm_send_reply(&ustcomm_app.server, ptr, src);
free(ptr);
- }
- else if(!strcmp(recvbuf, "start")) {
+ } else if (!strcmp(recvbuf, "print_trace_events")) {
+ print_trace_events(stderr);
+
+ } else if(!strcmp(recvbuf, "list_trace_events")) {
+ char *ptr;
+ size_t size;
+ FILE *fp;
+
+ fp = open_memstream(&ptr, &size);
+ if (fp == NULL) {
+ ERR("opening memstream failed");
+ return -1;
+ }
+ print_trace_events(fp);
+ fclose(fp);
+
+ result = ustcomm_send_reply(&ustcomm_app.server, ptr, src);
+ if (result < 0) {
+ ERR("list_trace_events failed");
+ return -1;
+ }
+ free(ptr);
+ } else if(!strcmp(recvbuf, "start")) {
/* start is an operation that setups the trace, allocates it and starts it */
result = ltt_trace_setup(trace_name);
if(result < 0) {
result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
- if(marker_name == NULL) {
+ if(channel_name == NULL || marker_name == NULL) {
+ WARN("invalid marker name");
+ goto next_cmd;
}
result = ltt_marker_disconnect(channel_name, marker_name, "default");
else if(nth_token_is(recvbuf, "get_pidunique", 0) == 1) {
char *reply;
- asprintf(&reply, "%lld", pidunique);
+ if (asprintf(&reply, "%lld", pidunique) < 0) {
+ ERR("process_client_cmd : asprintf failed (%lld)",
+ pidunique);
+ goto next_cmd;
+ }
result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
if(result) {
free(reply);
}
+ else if(nth_token_is(recvbuf, "get_sock_path", 0) == 1) {
+ char *reply = getenv("UST_DAEMON_SOCKET");
+ if(!reply) {
+ if (asprintf(&reply, "%s/%s", SOCK_DIR, "ustd") < 0) {
+ ERR("process_client_cmd : asprintf failed (%s/ustd)",
+ SOCK_DIR);
+ goto next_cmd;
+ }
+ result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
+ free(reply);
+ }
+ else {
+ result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
+ }
+ if(result)
+ ERR("ustcomm_send_reply failed");
+ }
+ else if(nth_token_is(recvbuf, "set_sock_path", 0) == 1) {
+ char *sock_path = nth_token(recvbuf, 1);
+ result = setenv("UST_DAEMON_SOCKET", sock_path, 1);
+ if(result)
+ ERR("cannot set UST_DAEMON_SOCKET environment variable");
+ }
+ else if(nth_token_is(recvbuf, "force_switch", 0) == 1) {
+ do_cmd_force_switch();
+ }
else {
ERR("unable to parse message: %s", recvbuf);
}
if(result) {
PERROR("pthread_sigmask: %s", strerror(result));
}
-
- have_listener = 1;
+ else {
+ have_listener = 1;
+ }
}
static int init_socket(void)
return result;
}
-static void stop_listener()
+static void stop_listener(void)
{
int result;
+ if(!have_listener)
+ return;
+
result = pthread_cancel(listener_thread);
if(result != 0) {
ERR("pthread_cancel: %s", strerror(result));