X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=libust%2Ftracectl.c;h=584a94cff8067e36626bd537bb7ac1d48731ee25;hb=c1f205309da615f1f0c68beedf37365942246537;hp=51460d185e6c8378a87dc7c236df7ea97698ea12;hpb=7958de40dc52ee7b1bda6b74eec7f3e60fbb6591;p=ust.git diff --git a/libust/tracectl.c b/libust/tracectl.c index 51460d1..584a94c 100644 --- a/libust/tracectl.c +++ b/libust/tracectl.c @@ -27,13 +27,14 @@ #include #include -#include +#include -#include "marker.h" +#include +#include #include "tracer.h" -#include "localerr.h" +#include "usterr.h" #include "ustcomm.h" -#include "relay.h" /* FIXME: remove */ +#include "buffers.h" /* FIXME: remove */ #include "marker-control.h" //#define USE_CLONE @@ -63,10 +64,6 @@ struct tracecmd { /* no padding */ /* volatile because shared between the listener and the main thread */ volatile sig_atomic_t buffers_to_export = 0; -//struct listener_arg { -// int pipe_fd; -//}; - struct trctl_msg { /* size: the size of all the fields except size itself */ uint32_t size; @@ -91,9 +88,8 @@ struct blocked_consumer { struct ustcomm_server server; struct ustcomm_source src; - /* args to ltt_do_get_subbuf */ - struct rchan_buf *rbuf; - struct ltt_channel_buf_struct *lttbuf; + /* args to ust_buffers_do_get_subbuf */ + struct ust_buffer *buf; struct list_head list; }; @@ -121,7 +117,7 @@ static void print_markers(FILE *fp) marker_iter_start(&iter); while(iter.marker) { - fprintf(fp, "marker: %s/%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format); + fprintf(fp, "marker: %s/%s %d \"%s\" %p\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format, iter.marker->location); marker_iter_next(&iter); } unlock_markers(); @@ -254,13 +250,13 @@ void process_blocked_consumers(void) continue; } - result = ltt_do_get_subbuf(bc->rbuf, bc->lttbuf, &consumed_old); + result = ust_buffers_do_get_subbuf(bc->buf, &consumed_old); if(result == -EAGAIN) { WARN("missed buffer?"); continue; } else if(result < 0) { - DBG("ltt_do_get_subbuf: error: %s", strerror(-result)); + DBG("ust_buffers_do_get_subbuf: error: %s", strerror(-result)); } asprintf(&reply, "%s %ld", "OK", consumed_old); result = ustcomm_send_reply(&bc->server, reply, &bc->src); @@ -375,6 +371,29 @@ void *listener_main(void *p) return (void *)1; } } + else if(!strcmp(recvbuf, "trace_create")) { + DBG("trace create"); + + result = ltt_trace_setup(trace_name); + if(result < 0) { + ERR("ltt_trace_setup failed"); + return (void *)1; + } + + result = ltt_trace_set_type(trace_name, trace_type); + if(result < 0) { + ERR("ltt_trace_set_type failed"); + return (void *)1; + } + + result = ltt_trace_alloc(trace_name); + if(result < 0) { + ERR("ltt_trace_alloc failed"); + return (void *)1; + } + + inform_consumer_daemon(trace_name); + } else if(!strcmp(recvbuf, "trace_start")) { DBG("trace start"); @@ -427,16 +446,15 @@ void *listener_main(void *p) } for(i=0; inr_channels; i++) { - struct rchan *rchan = trace->channels[i].trans_channel_data; - struct rchan_buf *rbuf = rchan->buf; - struct ltt_channel_struct *ltt_channel = (struct ltt_channel_struct *)rchan->private_data; + struct ust_channel *channel = &trace->channels[i]; + struct ust_buffer *buf = channel->buf; if(!strcmp(trace->channels[i].channel_name, channel_name)) { char *reply; - DBG("the shmid for the requested channel is %d", rbuf->shmid); - DBG("the shmid for its buffer structure is %d", ltt_channel->buf_shmid); - asprintf(&reply, "%d %d", rbuf->shmid, ltt_channel->buf_shmid); + DBG("the shmid for the requested channel is %d", buf->shmid); + DBG("the shmid for its buffer structure is %d", channel->buf_shmid); + asprintf(&reply, "%d %d", buf->shmid, channel->buf_shmid); result = ustcomm_send_reply(&ustcomm_app.server, reply, &src); if(result) { @@ -476,13 +494,13 @@ void *listener_main(void *p) } for(i=0; inr_channels; i++) { - struct rchan *rchan = trace->channels[i].trans_channel_data; + struct ust_channel *channel = &trace->channels[i]; if(!strcmp(trace->channels[i].channel_name, channel_name)) { char *reply; - DBG("the n_subbufs for the requested channel is %zd", rchan->n_subbufs); - asprintf(&reply, "%zd", rchan->n_subbufs); + DBG("the n_subbufs for the requested channel is %d", channel->subbuf_cnt); + asprintf(&reply, "%d", channel->subbuf_cnt); result = ustcomm_send_reply(&ustcomm_app.server, reply, &src); if(result) { @@ -520,13 +538,13 @@ void *listener_main(void *p) } for(i=0; inr_channels; i++) { - struct rchan *rchan = trace->channels[i].trans_channel_data; + struct ust_channel *channel = &trace->channels[i]; if(!strcmp(trace->channels[i].channel_name, channel_name)) { char *reply; - DBG("the subbuf_size for the requested channel is %zd", rchan->subbuf_size); - asprintf(&reply, "%zd", rchan->subbuf_size); + DBG("the subbuf_size for the requested channel is %zd", channel->subbuf_size); + asprintf(&reply, "%zd", channel->subbuf_size); result = ustcomm_send_reply(&ustcomm_app.server, reply, &src); if(result) { @@ -571,11 +589,10 @@ void *listener_main(void *p) } for(i=0; inr_channels; i++) { - struct rchan *rchan = trace->channels[i].trans_channel_data; + struct ust_channel *channel = &trace->channels[i]; if(!strcmp(trace->channels[i].channel_name, channel_name)) { - struct rchan_buf *rbuf = rchan->buf; - struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf; + struct ust_buffer *buf = channel->buf; struct blocked_consumer *bc; bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer)); @@ -584,9 +601,8 @@ void *listener_main(void *p) goto next_cmd; } bc->fd_consumer = src.fd; - bc->fd_producer = lttbuf->data_ready_fd_read; - bc->rbuf = rbuf; - bc->lttbuf = lttbuf; + bc->fd_producer = buf->data_ready_fd_read; + bc->buf = buf; bc->src = src; bc->server = ustcomm_app.server; @@ -634,21 +650,20 @@ void *listener_main(void *p) } for(i=0; inr_channels; i++) { - struct rchan *rchan = trace->channels[i].trans_channel_data; + struct ust_channel *channel = &trace->channels[i]; if(!strcmp(trace->channels[i].channel_name, channel_name)) { - struct rchan_buf *rbuf = rchan->buf; - struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf; + struct ust_buffer *buf = channel->buf; char *reply; long consumed_old=0; - result = ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); + result = ust_buffers_do_put_subbuf(buf, consumed_old); if(result < 0) { - WARN("ltt_do_put_subbuf: error (subbuf=%s)", channel_name); + WARN("ust_buffers_do_put_subbuf: error (subbuf=%s)", channel_name); asprintf(&reply, "%s", "ERROR"); } else { - DBG("ltt_do_put_subbuf: success (subbuf=%s)", channel_name); + DBG("ust_buffers_do_put_subbuf: success (subbuf=%s)", channel_name); asprintf(&reply, "%s", "OK"); } @@ -678,7 +693,6 @@ void *listener_main(void *p) WARN("invalid marker name"); goto next_cmd; } - printf("%s %s\n", channel_name, marker_name); result = ltt_marker_connect(channel_name, marker_name, "default"); if(result < 0) { @@ -694,7 +708,6 @@ void *listener_main(void *p) if(marker_name == NULL) { } - printf("%s %s\n", channel_name, marker_name); result = ltt_marker_disconnect(channel_name, marker_name, "default"); if(result < 0) { @@ -778,15 +791,18 @@ void create_listener(void) { #ifdef USE_CLONE static char listener_stack[16384]; + int result; #else pthread_t thread; #endif - if(have_listener) + if(have_listener) { + WARN("not creating listener because we already had one"); return; + } #ifdef USE_CLONE - result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL); + result = clone((int (*)(void *)) listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL); if(result == -1) { perror("clone"); return; @@ -799,61 +815,11 @@ void create_listener(void) have_listener = 1; } -/* The signal handler itself. Signals must be setup so there cannot be - nested signals. */ - -void sighandler(int sig) -{ - DBG("sighandler"); - - if(!have_listener) { - create_listener(); - } -} - -/* Called by the app signal handler to chain it to us. */ - -void chain_signal(void) -{ - sighandler(USTSIGNAL); -} - static int init_socket(void) { return ustcomm_init_app(getpid(), &ustcomm_app); } -static int init_signal_handler(void) -{ - /* Attempt to handler SIGIO. If the main program wants to - * handle it, fine, it'll override us. They it'll have to - * use the chaining function. - */ - - int result; - struct sigaction act; - - result = sigemptyset(&act.sa_mask); - if(result == -1) { - PERROR("sigemptyset"); - return -1; - } - - act.sa_handler = sighandler; - act.sa_flags = SA_RESTART; - - /* Only defer ourselves. Also, try to restart interrupted - * syscalls to disturb the traced program as little as possible. - */ - result = sigaction(SIGIO, &act, NULL); - if(result == -1) { - PERROR("sigaction"); - return -1; - } - - return 0; -} - #define AUTOPROBE_DISABLED 0 #define AUTOPROBE_ENABLE_ALL 1 #define AUTOPROBE_ENABLE_REGEX 2 @@ -888,11 +854,11 @@ static void auto_probe_connect(struct marker *m) if(result && result != -EEXIST) ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result); - DBG("auto connected marker %s %s to probe default", m->channel, m->name); + DBG("auto connected marker %s (addr: %p) %s to probe default", m->channel, m, m->name); } -static void __attribute__((constructor(1000))) init() +static void __attribute__((constructor)) init() { int result; char* autoprobe_val = NULL; @@ -917,11 +883,8 @@ static void __attribute__((constructor(1000))) init() ERR("init_socket error"); return; } - result = init_signal_handler(); - if(result == -1) { - ERR("init_signal_handler error"); - return; - } + + create_listener(); autoprobe_val = getenv("UST_AUTOPROBE"); if(autoprobe_val) { @@ -985,7 +948,24 @@ static void __attribute__((constructor(1000))) init() /* Ensure markers are initialized */ init_markers(); - /* In case. */ + /* FIXME: When starting early tracing (here), depending on the + * order of constructors, it is very well possible some marker + * sections are not yet registered. Because of this, some + * channels may not be registered. Yet, we are about to ask the + * daemon to collect the channels. Channels which are not yet + * registered will not be collected. + * + * Currently, in LTTng, there is no way to add a channel after + * trace start. The reason for this is that it induces complex + * concurrency issues on the trace structures, which can only + * be resolved using RCU. This has not been done yet. As a + * workaround, we are forcing the registration of the "ust" + * channel here. This is the only channel (apart from metadata) + * that can be reliably used in early tracing. + * + * Non-early tracing does not have this problem and can use + * arbitrary channel names. + */ ltt_channels_register("ust"); result = ltt_trace_setup(trace_name); @@ -1006,13 +986,15 @@ static void __attribute__((constructor(1000))) init() return; } - inform_consumer_daemon(trace_name); - result = ltt_trace_start(trace_name); if(result < 0) { ERR("ltt_trace_start failed"); return; } + + /* Do this after the trace is started in order to avoid creating confusion + * if the trace fails to start. */ + inform_consumer_daemon(trace_name); } @@ -1130,6 +1112,8 @@ void ust_potential_exec(void) { trace_mark(ust, potential_exec, MARK_NOARGS); + DBG("test"); + keepalive(); } @@ -1137,9 +1121,13 @@ void ust_potential_exec(void) * the new process, anytime a process whose memory is not shared with * the parent is created. If this function is not called, the events * of the new process will not be collected. + * + * Signals should be disabled before the fork and reenabled only after + * this call in order to guarantee tracing is not started before ust_fork() + * sanitizes the new process. */ -void ust_fork(void) +static void ust_fork(void) { struct blocked_consumer *bc; struct blocked_consumer *deletable_bc = NULL; @@ -1175,3 +1163,55 @@ void ust_fork(void) inform_consumer_daemon("auto"); } +void ust_before_fork(ust_fork_info_t *fork_info) +{ + /* Disable signals. This is to avoid that the child + * intervenes before it is properly setup for tracing. It is + * safer to disable all signals, because then we know we are not + * breaking anything by restoring the original mask. + */ + sigset_t all_sigs; + int result; + + /* FIXME: + - only do this if tracing is active + */ + + /* Disable signals */ + sigfillset(&all_sigs); + result = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs); + if(result == -1) { + PERROR("sigprocmask"); + return; + } +} + +/* Don't call this function directly in a traced program */ +static void ust_after_fork_common(ust_fork_info_t *fork_info) +{ + int result; + sigset_t orig_sigs; + + /* Restore signals */ + result = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL); + if(result == -1) { + PERROR("sigprocmask"); + return; + } +} + +void ust_after_fork_parent(ust_fork_info_t *fork_info) +{ + /* Reenable signals */ + ust_after_fork_common(fork_info); +} + +void ust_after_fork_child(ust_fork_info_t *fork_info) +{ + /* First sanitize the child */ + ust_fork(); + + /* Then reenable interrupts */ + ust_after_fork_common(fork_info); +} +