ustd: stop collecting a process when it died will trying to put its subbuffer
[lttng-ust.git] / libust / tracectl.c
CommitLineData
c39c72ee
PMF
1/* Copyright (C) 2009 Pierre-Marc Fournier
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
872037bb 18#define _GNU_SOURCE
68c1021b
PMF
19#include <stdio.h>
20#include <stdint.h>
21#include <signal.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <sys/un.h>
98963de4 25#include <sched.h>
a584bc4e 26#include <fcntl.h>
3a7b90de 27#include <poll.h>
ef290fca 28#include <regex.h>
fbd8191b 29
26cc7017
PMF
30#include <urcu.h>
31
fbd8191b 32#include "marker.h"
a584bc4e 33#include "tracer.h"
d0b5f2b9
PMF
34#include "localerr.h"
35#include "ustcomm.h"
46ef48cd 36#include "relay.h" /* FIXME: remove */
9160b4e4 37#include "marker-control.h"
fbd8191b 38
b02e31e5 39//#define USE_CLONE
3847c3ba 40
68c1021b
PMF
41#define USTSIGNAL SIGIO
42
98963de4
PMF
43#define MAX_MSG_SIZE (100)
44#define MSG_NOTIF 1
45#define MSG_REGISTER_NOTIF 2
46
a584bc4e
PMF
47char consumer_stack[10000];
48
ed1317e7
PMF
49/* This should only be accessed by the constructor, before the creation
50 * of the listener, and then only by the listener.
51 */
52s64 pidunique = -1LL;
53
3a7b90de
PMF
54struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
55
d0b5f2b9
PMF
56static struct ustcomm_app ustcomm_app;
57
68c1021b
PMF
58struct tracecmd { /* no padding */
59 uint32_t size;
60 uint16_t command;
61};
62
f293009f
PMF
63/* volatile because shared between the listener and the main thread */
64volatile sig_atomic_t buffers_to_export = 0;
65
98963de4
PMF
66//struct listener_arg {
67// int pipe_fd;
68//};
69
70struct trctl_msg {
71 /* size: the size of all the fields except size itself */
72 uint32_t size;
73 uint16_t type;
74 /* Only the necessary part of the payload is transferred. It
75 * may even be none of it.
76 */
77 char payload[94];
78};
68c1021b 79
a584bc4e
PMF
80struct consumer_channel {
81 int fd;
82 struct ltt_channel_struct *chan;
83};
84
3a7b90de
PMF
85struct blocked_consumer {
86 int fd_consumer;
87 int fd_producer;
88 int tmp_poll_idx;
89
90 /* args to ustcomm_send_reply */
91 struct ustcomm_server server;
92 struct ustcomm_source src;
93
94 /* args to ltt_do_get_subbuf */
95 struct rchan_buf *rbuf;
96 struct ltt_channel_buf_struct *lttbuf;
97
98 struct list_head list;
99};
100
ed1317e7
PMF
101static long long make_pidunique(void)
102{
103 s64 retval;
104 struct timeval tv;
105
106 gettimeofday(&tv, NULL);
107
108 retval = tv.tv_sec;
109 retval <<= 32;
110 retval |= tv.tv_usec;
111
112 return retval;
113}
114
52c51a47 115static void print_markers(FILE *fp)
fbd8191b
PMF
116{
117 struct marker_iter iter;
118
d0b5f2b9 119 lock_markers();
fbd8191b
PMF
120 marker_iter_reset(&iter);
121 marker_iter_start(&iter);
122
123 while(iter.marker) {
52c51a47 124 fprintf(fp, "marker: %s_%s %d \"%s\"\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format);
fbd8191b
PMF
125 marker_iter_next(&iter);
126 }
d0b5f2b9 127 unlock_markers();
fbd8191b
PMF
128}
129
4440ebcb 130static int init_socket(void);
68c1021b 131
26cc7017
PMF
132/* This needs to be called whenever a new thread is created. It notifies
133 * liburcu of the new thread.
134 */
135
136void ust_register_thread(void)
68c1021b 137{
26cc7017 138 rcu_register_thread();
68c1021b
PMF
139}
140
98963de4
PMF
141int fd_notif = -1;
142void notif_cb(void)
143{
144 int result;
145 struct trctl_msg msg;
146
147 /* FIXME: fd_notif should probably be protected by a spinlock */
148
149 if(fd_notif == -1)
150 return;
151
152 msg.type = MSG_NOTIF;
153 msg.size = sizeof(msg.type);
154
155 /* FIXME: don't block here */
156 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
157 if(result == -1) {
158 PERROR("write");
159 return;
160 }
161}
162
ad45e833
PMF
163/* Ask the daemon to collect a trace called trace_name and being
164 * produced by this pid.
165 *
166 * The trace must be at least allocated. (It can also be started.)
167 * This is because _ltt_trace_find is used.
168 */
169
170static void inform_consumer_daemon(const char *trace_name)
d0b5f2b9 171{
ad45e833
PMF
172 int i;
173 struct ltt_trace_struct *trace;
174 pid_t pid = getpid();
175 int result;
176
177 ltt_lock_traces();
178
179 trace = _ltt_trace_find(trace_name);
180 if(trace == NULL) {
181 WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
182 goto finish;
183 }
184
185 for(i=0; i < trace->nr_channels; i++) {
186 result = ustcomm_request_consumer(pid, trace->channels[i].channel_name);
187 if(result == -1) {
188 WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
189 /* continue even if fail */
190 }
f293009f 191 buffers_to_export++;
ad45e833
PMF
192 }
193
194 finish:
195 ltt_unlock_traces();
d0b5f2b9 196}
fbd8191b 197
3a7b90de
PMF
198void process_blocked_consumers(void)
199{
200 int n_fds = 0;
201 struct pollfd *fds;
202 struct blocked_consumer *bc;
203 int idx = 0;
204 char inbuf;
205 int result;
206
207 list_for_each_entry(bc, &blocked_consumers, list) {
208 n_fds++;
209 }
210
211 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
212 if(fds == NULL) {
213 ERR("malloc returned NULL");
214 return;
215 }
216
217 list_for_each_entry(bc, &blocked_consumers, list) {
218 fds[idx].fd = bc->fd_producer;
219 fds[idx].events = POLLIN;
220 bc->tmp_poll_idx = idx;
221 idx++;
222 }
223
69ba0156
PMF
224 while((result = poll(fds, n_fds, 0)) == -1 && errno == EINTR)
225 /* nothing */;
3a7b90de
PMF
226 if(result == -1) {
227 PERROR("poll");
872037bb 228 return;
3a7b90de
PMF
229 }
230
231 list_for_each_entry(bc, &blocked_consumers, list) {
232 if(fds[bc->tmp_poll_idx].revents) {
233 long consumed_old = 0;
234 char *reply;
235
236 result = read(bc->fd_producer, &inbuf, 1);
237 if(result == -1) {
238 PERROR("read");
239 continue;
240 }
241 if(result == 0) {
242 DBG("PRODUCER END");
243
244 close(bc->fd_producer);
245
769d0157 246 list_del(&bc->list);
3a7b90de
PMF
247
248 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
249 if(result < 0) {
250 ERR("ustcomm_send_reply failed");
251 continue;
252 }
253
254 continue;
255 }
256
257 result = ltt_do_get_subbuf(bc->rbuf, bc->lttbuf, &consumed_old);
258 if(result == -EAGAIN) {
259 WARN("missed buffer?");
260 continue;
261 }
262 else if(result < 0) {
263 DBG("ltt_do_get_subbuf: error: %s", strerror(-result));
264 }
265 asprintf(&reply, "%s %ld", "OK", consumed_old);
266 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
267 if(result < 0) {
268 ERR("ustcomm_send_reply failed");
269 free(reply);
270 continue;
271 }
272 free(reply);
273
769d0157 274 list_del(&bc->list);
3a7b90de
PMF
275 }
276 }
277
278}
279
872037bb 280void *listener_main(void *p)
98963de4
PMF
281{
282 int result;
283
26cc7017
PMF
284 ust_register_thread();
285
b0540e11
PMF
286 DBG("LISTENER");
287
98963de4 288 for(;;) {
aafb1650
PMF
289 char trace_name[] = "auto";
290 char trace_type[] = "ustrelay";
d0b5f2b9
PMF
291 char *recvbuf;
292 int len;
b02e31e5 293 struct ustcomm_source src;
98963de4 294
3a7b90de
PMF
295 process_blocked_consumers();
296
297 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
298 if(result < 0) {
d0b5f2b9
PMF
299 WARN("error in ustcomm_app_recv_message");
300 continue;
301 }
3a7b90de
PMF
302 else if(result == 0) {
303 /* no message */
304 continue;
305 }
98963de4 306
08230db7 307 DBG("received a message! it's: %s", recvbuf);
d0b5f2b9 308 len = strlen(recvbuf);
98963de4 309
d0b5f2b9 310 if(!strcmp(recvbuf, "print_markers")) {
52c51a47
PMF
311 print_markers(stderr);
312 }
313 else if(!strcmp(recvbuf, "list_markers")) {
314 char *ptr;
315 size_t size;
316 FILE *fp;
317
318 fp = open_memstream(&ptr, &size);
319 print_markers(fp);
320 fclose(fp);
321
322 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
323
324 free(ptr);
325 }
326 else if(!strcmp(recvbuf, "start")) {
327 /* start is an operation that setups the trace, allocates it and starts it */
328 result = ltt_trace_setup(trace_name);
329 if(result < 0) {
330 ERR("ltt_trace_setup failed");
872037bb 331 return (void *)1;
52c51a47
PMF
332 }
333
334 result = ltt_trace_set_type(trace_name, trace_type);
335 if(result < 0) {
336 ERR("ltt_trace_set_type failed");
872037bb 337 return (void *)1;
52c51a47
PMF
338 }
339
340 result = ltt_trace_alloc(trace_name);
341 if(result < 0) {
342 ERR("ltt_trace_alloc failed");
872037bb 343 return (void *)1;
52c51a47
PMF
344 }
345
ad45e833 346 inform_consumer_daemon(trace_name);
52c51a47
PMF
347
348 result = ltt_trace_start(trace_name);
349 if(result < 0) {
350 ERR("ltt_trace_start failed");
351 continue;
352 }
d0b5f2b9
PMF
353 }
354 else if(!strcmp(recvbuf, "trace_setup")) {
355 DBG("trace setup");
fbd8191b 356
d0b5f2b9
PMF
357 result = ltt_trace_setup(trace_name);
358 if(result < 0) {
359 ERR("ltt_trace_setup failed");
872037bb 360 return (void *)1;
fbd8191b 361 }
d0b5f2b9
PMF
362
363 result = ltt_trace_set_type(trace_name, trace_type);
364 if(result < 0) {
365 ERR("ltt_trace_set_type failed");
872037bb 366 return (void *)1;
fbd8191b 367 }
d0b5f2b9
PMF
368 }
369 else if(!strcmp(recvbuf, "trace_alloc")) {
370 DBG("trace alloc");
371
372 result = ltt_trace_alloc(trace_name);
373 if(result < 0) {
374 ERR("ltt_trace_alloc failed");
872037bb 375 return (void *)1;
fbd8191b 376 }
d0b5f2b9
PMF
377 }
378 else if(!strcmp(recvbuf, "trace_start")) {
379 DBG("trace start");
380
381 result = ltt_trace_start(trace_name);
382 if(result < 0) {
383 ERR("ltt_trace_start failed");
384 continue;
fbd8191b 385 }
d0b5f2b9
PMF
386 }
387 else if(!strcmp(recvbuf, "trace_stop")) {
388 DBG("trace stop");
389
390 result = ltt_trace_stop(trace_name);
391 if(result < 0) {
392 ERR("ltt_trace_stop failed");
872037bb 393 return (void *)1;
aafb1650 394 }
d0b5f2b9
PMF
395 }
396 else if(!strcmp(recvbuf, "trace_destroy")) {
aafb1650 397
d0b5f2b9 398 DBG("trace destroy");
aafb1650 399
d0b5f2b9
PMF
400 result = ltt_trace_destroy(trace_name);
401 if(result < 0) {
402 ERR("ltt_trace_destroy failed");
872037bb 403 return (void *)1;
fbd8191b 404 }
98963de4 405 }
b02e31e5 406 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
3847c3ba
PMF
407 struct ltt_trace_struct *trace;
408 char trace_name[] = "auto";
409 int i;
811e4b93 410 char *channel_name;
3847c3ba
PMF
411
412 DBG("get_shmid");
413
811e4b93
PMF
414 channel_name = nth_token(recvbuf, 1);
415 if(channel_name == NULL) {
416 ERR("get_shmid: cannot parse channel");
417 goto next_cmd;
418 }
419
3847c3ba
PMF
420 ltt_lock_traces();
421 trace = _ltt_trace_find(trace_name);
422 ltt_unlock_traces();
423
424 if(trace == NULL) {
63fe14e5 425 ERR("cannot find trace!");
872037bb 426 return (void *)1;
3847c3ba
PMF
427 }
428
429 for(i=0; i<trace->nr_channels; i++) {
430 struct rchan *rchan = trace->channels[i].trans_channel_data;
431 struct rchan_buf *rbuf = rchan->buf;
8cefc145 432 struct ltt_channel_struct *ltt_channel = (struct ltt_channel_struct *)rchan->private_data;
3847c3ba 433
811e4b93
PMF
434 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
435 char *reply;
436
437 DBG("the shmid for the requested channel is %d", rbuf->shmid);
8cefc145
PMF
438 DBG("the shmid for its buffer structure is %d", ltt_channel->buf_shmid);
439 asprintf(&reply, "%d %d", rbuf->shmid, ltt_channel->buf_shmid);
811e4b93
PMF
440
441 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
442 if(result) {
443 ERR("listener: get_shmid: ustcomm_send_reply failed");
444 goto next_cmd;
445 }
446
447 free(reply);
448
449 break;
450 }
451 }
f293009f
PMF
452
453 buffers_to_export--;
811e4b93
PMF
454 }
455 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
456 struct ltt_trace_struct *trace;
457 char trace_name[] = "auto";
458 int i;
459 char *channel_name;
460
461 DBG("get_n_subbufs");
462
463 channel_name = nth_token(recvbuf, 1);
464 if(channel_name == NULL) {
465 ERR("get_n_subbufs: cannot parse channel");
466 goto next_cmd;
467 }
468
469 ltt_lock_traces();
470 trace = _ltt_trace_find(trace_name);
471 ltt_unlock_traces();
472
473 if(trace == NULL) {
63fe14e5 474 ERR("cannot find trace!");
872037bb 475 return (void *)1;
811e4b93
PMF
476 }
477
478 for(i=0; i<trace->nr_channels; i++) {
479 struct rchan *rchan = trace->channels[i].trans_channel_data;
480
481 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
482 char *reply;
483
872037bb
PMF
484 DBG("the n_subbufs for the requested channel is %zd", rchan->n_subbufs);
485 asprintf(&reply, "%zd", rchan->n_subbufs);
811e4b93
PMF
486
487 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
488 if(result) {
489 ERR("listener: get_n_subbufs: ustcomm_send_reply failed");
490 goto next_cmd;
491 }
492
493 free(reply);
494
495 break;
496 }
497 }
498 }
499 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
500 struct ltt_trace_struct *trace;
501 char trace_name[] = "auto";
502 int i;
503 char *channel_name;
504
505 DBG("get_subbuf_size");
506
507 channel_name = nth_token(recvbuf, 1);
508 if(channel_name == NULL) {
509 ERR("get_subbuf_size: cannot parse channel");
510 goto next_cmd;
511 }
512
513 ltt_lock_traces();
514 trace = _ltt_trace_find(trace_name);
515 ltt_unlock_traces();
516
517 if(trace == NULL) {
63fe14e5 518 ERR("cannot find trace!");
872037bb 519 return (void *)1;
811e4b93
PMF
520 }
521
522 for(i=0; i<trace->nr_channels; i++) {
523 struct rchan *rchan = trace->channels[i].trans_channel_data;
524
525 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
526 char *reply;
527
872037bb
PMF
528 DBG("the subbuf_size for the requested channel is %zd", rchan->subbuf_size);
529 asprintf(&reply, "%zd", rchan->subbuf_size);
811e4b93
PMF
530
531 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
532 if(result) {
533 ERR("listener: get_subbuf_size: ustcomm_send_reply failed");
534 goto next_cmd;
535 }
536
537 free(reply);
3847c3ba 538
811e4b93
PMF
539 break;
540 }
3847c3ba
PMF
541 }
542 }
b02e31e5
PMF
543 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
544 char *libfile;
545
546 libfile = nth_token(recvbuf, 1);
547
548 DBG("load_probe_lib loading %s", libfile);
549 }
688760ef
PMF
550 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
551 struct ltt_trace_struct *trace;
552 char trace_name[] = "auto";
553 int i;
554 char *channel_name;
555
556 DBG("get_subbuf");
557
558 channel_name = nth_token(recvbuf, 1);
559 if(channel_name == NULL) {
560 ERR("get_subbuf: cannot parse channel");
561 goto next_cmd;
562 }
563
564 ltt_lock_traces();
565 trace = _ltt_trace_find(trace_name);
566 ltt_unlock_traces();
567
568 if(trace == NULL) {
63fe14e5 569 ERR("cannot find trace!");
872037bb 570 return (void *)1;
688760ef
PMF
571 }
572
573 for(i=0; i<trace->nr_channels; i++) {
574 struct rchan *rchan = trace->channels[i].trans_channel_data;
575
576 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
577 struct rchan_buf *rbuf = rchan->buf;
578 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
3a7b90de 579 struct blocked_consumer *bc;
688760ef 580
3a7b90de
PMF
581 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
582 if(bc == NULL) {
583 ERR("malloc returned NULL");
688760ef
PMF
584 goto next_cmd;
585 }
3a7b90de
PMF
586 bc->fd_consumer = src.fd;
587 bc->fd_producer = lttbuf->data_ready_fd_read;
588 bc->rbuf = rbuf;
589 bc->lttbuf = lttbuf;
590 bc->src = src;
591 bc->server = ustcomm_app.server;
688760ef 592
3a7b90de 593 list_add(&bc->list, &blocked_consumers);
688760ef
PMF
594
595 break;
596 }
597 }
598 }
599 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
600 struct ltt_trace_struct *trace;
601 char trace_name[] = "auto";
602 int i;
603 char *channel_name;
604 long consumed_old;
605 char *consumed_old_str;
606 char *endptr;
607
608 DBG("put_subbuf");
609
610 channel_name = strdup_malloc(nth_token(recvbuf, 1));
611 if(channel_name == NULL) {
612 ERR("put_subbuf_size: cannot parse channel");
613 goto next_cmd;
614 }
615
616 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
617 if(consumed_old_str == NULL) {
618 ERR("put_subbuf: cannot parse consumed_old");
619 goto next_cmd;
620 }
621 consumed_old = strtol(consumed_old_str, &endptr, 10);
622 if(*endptr != '\0') {
623 ERR("put_subbuf: invalid value for consumed_old");
624 goto next_cmd;
625 }
626
627 ltt_lock_traces();
628 trace = _ltt_trace_find(trace_name);
629 ltt_unlock_traces();
630
631 if(trace == NULL) {
63fe14e5 632 ERR("cannot find trace!");
872037bb 633 return (void *)1;
688760ef
PMF
634 }
635
636 for(i=0; i<trace->nr_channels; i++) {
637 struct rchan *rchan = trace->channels[i].trans_channel_data;
638
639 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
640 struct rchan_buf *rbuf = rchan->buf;
641 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
642 char *reply;
643 long consumed_old=0;
644
645 result = ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
646 if(result < 0) {
0a58610f 647 WARN("ltt_do_put_subbuf: error (subbuf=%s)", channel_name);
872037bb 648 asprintf(&reply, "%s", "ERROR");
688760ef
PMF
649 }
650 else {
0a58610f 651 DBG("ltt_do_put_subbuf: success (subbuf=%s)", channel_name);
872037bb 652 asprintf(&reply, "%s", "OK");
688760ef 653 }
688760ef
PMF
654
655 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
656 if(result) {
657 ERR("listener: put_subbuf: ustcomm_send_reply failed");
658 goto next_cmd;
659 }
660
661 free(reply);
662
663 break;
664 }
665 }
666
667 free(channel_name);
668 free(consumed_old_str);
669 }
52c51a47
PMF
670 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
671 char *channel_slash_name = nth_token(recvbuf, 1);
672 char channel_name[256]="";
673 char marker_name[256]="";
52c51a47
PMF
674
675 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
676
677 if(channel_name == NULL || marker_name == NULL) {
678 WARN("invalid marker name");
679 goto next_cmd;
680 }
681 printf("%s %s\n", channel_name, marker_name);
682
683 result = ltt_marker_connect(channel_name, marker_name, "default");
684 if(result < 0) {
685 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
686 }
687 }
688 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
689 char *channel_slash_name = nth_token(recvbuf, 1);
690 char *marker_name;
691 char *channel_name;
52c51a47
PMF
692
693 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
694
695 if(marker_name == NULL) {
696 }
697 printf("%s %s\n", channel_name, marker_name);
698
699 result = ltt_marker_disconnect(channel_name, marker_name, "default");
700 if(result < 0) {
701 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
702 }
703 }
ed1317e7
PMF
704 else if(nth_token_is(recvbuf, "get_pidunique", 0) == 1) {
705 char *reply;
706
707 asprintf(&reply, "%lld", pidunique);
708
709 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
710 if(result) {
711 ERR("listener: get_pidunique: ustcomm_send_reply failed");
712 goto next_cmd;
713 }
714
715 free(reply);
716 }
3a7b90de
PMF
717// else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
718// struct ltt_trace_struct *trace;
719// char trace_name[] = "auto";
720// int i;
721// char *channel_name;
722//
723// DBG("get_notifications");
724//
725// channel_name = strdup_malloc(nth_token(recvbuf, 1));
726// if(channel_name == NULL) {
727// ERR("put_subbuf_size: cannot parse channel");
728// goto next_cmd;
729// }
730//
731// ltt_lock_traces();
732// trace = _ltt_trace_find(trace_name);
733// ltt_unlock_traces();
734//
735// if(trace == NULL) {
63fe14e5 736// ERR("cannot find trace!");
872037bb 737// return (void *)1;
3a7b90de
PMF
738// }
739//
740// for(i=0; i<trace->nr_channels; i++) {
741// struct rchan *rchan = trace->channels[i].trans_channel_data;
742// int fd;
743//
744// if(!strcmp(trace->channels[i].channel_name, channel_name)) {
745// struct rchan_buf *rbuf = rchan->buf;
746// struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
747//
748// result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
749// if(result == -1) {
750// ERR("ustcomm_app_detach_client failed");
751// goto next_cmd;
752// }
753//
754// lttbuf->wake_consumer_arg = (void *) fd;
755//
756// smp_wmb();
757//
758// lttbuf->call_wake_consumer = 1;
759//
760// break;
761// }
762// }
763//
764// free(channel_name);
765// }
688760ef
PMF
766 else {
767 ERR("unable to parse message: %s", recvbuf);
768 }
d0b5f2b9 769
811e4b93 770 next_cmd:
d0b5f2b9 771 free(recvbuf);
98963de4
PMF
772 }
773}
774
4440ebcb
PMF
775int have_listener = 0;
776
98963de4
PMF
777void create_listener(void)
778{
9160b4e4 779#ifdef USE_CLONE
98963de4 780 static char listener_stack[16384];
4440ebcb
PMF
781#else
782 pthread_t thread;
9160b4e4 783#endif
98963de4 784
4440ebcb
PMF
785 if(have_listener)
786 return;
787
3847c3ba 788#ifdef USE_CLONE
fbd8191b 789 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
790 if(result == -1) {
791 perror("clone");
4440ebcb 792 return;
98963de4 793 }
3847c3ba 794#else
b0540e11 795
3847c3ba
PMF
796 pthread_create(&thread, NULL, listener_main, NULL);
797#endif
4440ebcb
PMF
798
799 have_listener = 1;
98963de4
PMF
800}
801
d0b5f2b9
PMF
802/* The signal handler itself. Signals must be setup so there cannot be
803 nested signals. */
68c1021b
PMF
804
805void sighandler(int sig)
806{
807 DBG("sighandler");
d0b5f2b9
PMF
808
809 if(!have_listener) {
810 create_listener();
d0b5f2b9 811 }
68c1021b
PMF
812}
813
814/* Called by the app signal handler to chain it to us. */
815
98963de4 816void chain_signal(void)
68c1021b
PMF
817{
818 sighandler(USTSIGNAL);
819}
820
98963de4 821static int init_socket(void)
68c1021b 822{
d0b5f2b9 823 return ustcomm_init_app(getpid(), &ustcomm_app);
68c1021b
PMF
824}
825
98963de4 826static int init_signal_handler(void)
68c1021b
PMF
827{
828 /* Attempt to handler SIGIO. If the main program wants to
829 * handle it, fine, it'll override us. They it'll have to
830 * use the chaining function.
831 */
832
833 int result;
834 struct sigaction act;
835
836 result = sigemptyset(&act.sa_mask);
837 if(result == -1) {
838 PERROR("sigemptyset");
839 return -1;
840 }
841
842 act.sa_handler = sighandler;
843 act.sa_flags = SA_RESTART;
844
845 /* Only defer ourselves. Also, try to restart interrupted
846 * syscalls to disturb the traced program as little as possible.
847 */
848 result = sigaction(SIGIO, &act, NULL);
849 if(result == -1) {
850 PERROR("sigaction");
851 return -1;
852 }
853
854 return 0;
855}
856
5de74e51
PMF
857#define AUTOPROBE_DISABLED 0
858#define AUTOPROBE_ENABLE_ALL 1
859#define AUTOPROBE_ENABLE_REGEX 2
860static int autoprobe_method = AUTOPROBE_DISABLED;
861static regex_t autoprobe_regex;
ef290fca 862
20b37a31 863static void auto_probe_connect(struct marker *m)
68c1021b
PMF
864{
865 int result;
866
5de74e51
PMF
867 char* concat_name = NULL;
868 const char *probe_name = "default";
ef290fca 869
5de74e51 870 if(autoprobe_method == AUTOPROBE_DISABLED) {
ef290fca
PMF
871 return;
872 }
5de74e51
PMF
873 else if(autoprobe_method == AUTOPROBE_ENABLE_REGEX) {
874 result = asprintf(&concat_name, "%s/%s", m->channel, m->name);
875 if(result == -1) {
876 ERR("auto_probe_connect: asprintf failed (marker %s/%s)",
877 m->channel, m->name);
878 return;
879 }
880 if (regexec(&autoprobe_regex, concat_name, 0, NULL, 0)) {
881 free(concat_name);
882 return;
883 }
884 free(concat_name);
ef290fca
PMF
885 }
886
5de74e51 887 result = ltt_marker_connect(m->channel, m->name, probe_name);
acbf228b
PMF
888 if(result && result != -EEXIST)
889 ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
20b37a31 890
5de74e51 891 DBG("auto connected marker %s %s to probe default", m->channel, m->name);
ef290fca 892
20b37a31
PMF
893}
894
895static void __attribute__((constructor(1000))) init()
896{
897 int result;
5de74e51 898 char* autoprobe_val = NULL;
20b37a31 899
ed1317e7
PMF
900 /* Assign the pidunique, to be able to differentiate the processes with same
901 * pid, (before and after an exec).
902 */
903 pidunique = make_pidunique();
904
4440ebcb
PMF
905 /* Initialize RCU in case the constructor order is not good. */
906 urcu_init();
907
908 /* It is important to do this before events start to be generated. */
909 ust_register_thread();
910
5de74e51 911 DBG("Tracectl constructor");
20b37a31 912
3847c3ba
PMF
913 /* Must create socket before signal handler to prevent races.
914 */
915 result = init_socket();
916 if(result == -1) {
917 ERR("init_socket error");
918 return;
919 }
920 result = init_signal_handler();
921 if(result == -1) {
922 ERR("init_signal_handler error");
923 return;
924 }
68c1021b 925
5de74e51
PMF
926 autoprobe_val = getenv("UST_AUTOPROBE");
927 if(autoprobe_val) {
4440ebcb
PMF
928 struct marker_iter iter;
929
08230db7 930 DBG("Autoprobe enabled.");
4440ebcb
PMF
931
932 /* Ensure markers are initialized */
933 //init_markers();
934
935 /* Ensure marker control is initialized, for the probe */
936 init_marker_control();
937
938 /* first, set the callback that will connect the
939 * probe on new markers
940 */
5de74e51
PMF
941 if(autoprobe_val[0] == '/') {
942 result = regcomp(&autoprobe_regex, autoprobe_val+1, 0);
943 if (result) {
944 char regexerr[150];
945
946 regerror(result, &autoprobe_regex, regexerr, sizeof(regexerr));
947 ERR("cannot parse regex %s (%s), will ignore UST_AUTOPROBE", autoprobe_val, regexerr);
948 /* don't crash the application just for this */
949 }
950 else {
951 autoprobe_method = AUTOPROBE_ENABLE_REGEX;
952 }
ef290fca 953 }
5de74e51
PMF
954 else {
955 /* just enable all instrumentation */
956 autoprobe_method = AUTOPROBE_ENABLE_ALL;
957 }
958
959 marker_set_new_marker_cb(auto_probe_connect);
960
4440ebcb
PMF
961 /* Now, connect the probes that were already registered. */
962 marker_iter_reset(&iter);
963 marker_iter_start(&iter);
964
08230db7 965 DBG("now iterating on markers already registered");
4440ebcb 966 while(iter.marker) {
08230db7 967 DBG("now iterating on marker %s", iter.marker->name);
4440ebcb
PMF
968 auto_probe_connect(iter.marker);
969 marker_iter_next(&iter);
970 }
971 }
972
4db647c5
PMF
973 if(getenv("UST_TRACE")) {
974 char trace_name[] = "auto";
975 char trace_type[] = "ustrelay";
976
977 DBG("starting early tracing");
978
979 /* Ensure marker control is initialized */
980 init_marker_control();
981
982 /* Ensure relay is initialized */
983 init_ustrelay_transport();
984
985 /* Ensure markers are initialized */
986 init_markers();
987
20b37a31
PMF
988 /* In case. */
989 ltt_channels_register("ust");
4db647c5
PMF
990
991 result = ltt_trace_setup(trace_name);
992 if(result < 0) {
993 ERR("ltt_trace_setup failed");
994 return;
995 }
996
997 result = ltt_trace_set_type(trace_name, trace_type);
998 if(result < 0) {
999 ERR("ltt_trace_set_type failed");
1000 return;
1001 }
1002
1003 result = ltt_trace_alloc(trace_name);
1004 if(result < 0) {
1005 ERR("ltt_trace_alloc failed");
1006 return;
1007 }
1008
ad45e833
PMF
1009 inform_consumer_daemon(trace_name);
1010
4db647c5
PMF
1011 result = ltt_trace_start(trace_name);
1012 if(result < 0) {
1013 ERR("ltt_trace_start failed");
1014 return;
1015 }
1016 }
1017
68c1021b
PMF
1018
1019 return;
1020
1021 /* should decrementally destroy stuff if error */
1022
1023}
1024
1025/* This is only called if we terminate normally, not with an unhandled signal,
6d45c11a
PMF
1026 * so we cannot rely on it. However, for now, LTTV requires that the header of
1027 * the last sub-buffer contain a valid end time for the trace. This is done
1028 * automatically only when the trace is properly stopped.
1029 *
1030 * If the traced program crashed, it is always possible to manually add the
1031 * right value in the header, or to open the trace in text mode.
1032 *
1033 * FIXME: Fix LTTV so it doesn't need this.
1034 */
68c1021b 1035
6d45c11a 1036static void destroy_traces(void)
68c1021b 1037{
6d45c11a 1038 int result;
a584bc4e
PMF
1039
1040 /* if trace running, finish it */
1041
6d45c11a 1042 DBG("destructor stopping traces");
a584bc4e 1043
6d45c11a
PMF
1044 result = ltt_trace_stop("auto");
1045 if(result == -1) {
1046 ERR("ltt_trace_stop error");
1047 }
1048
1049 result = ltt_trace_destroy("auto");
1050 if(result == -1) {
1051 ERR("ltt_trace_destroy error");
1052 }
68c1021b 1053}
1e2944cb 1054
97d9b88b
PMF
1055static int trace_recording(void)
1056{
1057 int retval = 0;
1058 struct ltt_trace_struct *trace;
1059
1060 ltt_lock_traces();
1061
1062 list_for_each_entry(trace, &ltt_traces.head, list) {
1063 if(trace->active) {
1064 retval = 1;
1065 break;
1066 }
1067 }
1068
1069 ltt_unlock_traces();
1070
1071 return retval;
1072}
1073
f293009f 1074#if 0
97d9b88b
PMF
1075static int have_consumer(void)
1076{
1077 return !list_empty(&blocked_consumers);
1078}
f293009f 1079#endif
97d9b88b 1080
f293009f 1081int restarting_usleep(useconds_t usecs)
97d9b88b
PMF
1082{
1083 struct timespec tv;
1084 int result;
1085
f293009f
PMF
1086 tv.tv_sec = 0;
1087 tv.tv_nsec = usecs * 1000;
97d9b88b
PMF
1088
1089 do {
1090 result = nanosleep(&tv, &tv);
1091 } while(result == -1 && errno == EINTR);
1092
1093 return result;
1094}
1095
f293009f
PMF
1096/* This destructor keeps the process alive for a few seconds in order
1097 * to leave time to ustd to connect to its buffers. This is necessary
1098 * for programs whose execution is very short. It is also useful in all
1099 * programs when tracing is started close to the end of the program
1100 * execution.
1101 *
1102 * FIXME: For now, this only works for the first trace created in a
1103 * process.
1104 */
1105
97d9b88b
PMF
1106static void __attribute__((destructor)) keepalive()
1107{
f293009f 1108 if(trace_recording() && buffers_to_export) {
c472cce0 1109 int total = 0;
f293009f
PMF
1110 DBG("Keeping process alive for consumer daemon...");
1111 while(buffers_to_export) {
1112 const int interv = 200000;
c472cce0 1113 restarting_usleep(interv);
f293009f
PMF
1114 total += interv;
1115
1116 if(total >= 3000000) {
c472cce0 1117 WARN("non-consumed buffers remaining after wait limit; not waiting anymore");
f293009f
PMF
1118 break;
1119 }
1120 }
1121 DBG("Finally dying...");
1122 }
6d45c11a
PMF
1123
1124 destroy_traces();
1125
1126 ustcomm_fini_app(&ustcomm_app);
97d9b88b 1127}
97d9b88b 1128
c396a841
PMF
1129void ust_potential_exec(void)
1130{
1131 trace_mark(ust, potential_exec, MARK_NOARGS);
1132
1133 keepalive();
1134}
1135
1e2944cb
PMF
1136/* Notify ust that there was a fork. This needs to be called inside
1137 * the new process, anytime a process whose memory is not shared with
1138 * the parent is created. If this function is not called, the events
1139 * of the new process will not be collected.
1140 */
1141
1142void ust_fork(void)
1143{
99b72dc0
PMF
1144 struct blocked_consumer *bc;
1145 struct blocked_consumer *deletable_bc = NULL;
1146 int result;
1147
1e2944cb
PMF
1148 DBG("ust: forking");
1149 ltt_trace_stop("auto");
1150 ltt_trace_destroy("auto");
99b72dc0
PMF
1151 /* Delete all active connections */
1152 ustcomm_close_all_connections(&ustcomm_app.server);
1153
1154 /* Delete all blocked consumers */
1155 list_for_each_entry(bc, &blocked_consumers, list) {
d9ce395d
PMF
1156 close(bc->fd_producer);
1157 close(bc->fd_consumer);
99b72dc0
PMF
1158 free(deletable_bc);
1159 deletable_bc = bc;
1160 list_del(&bc->list);
1161 }
1162
1e2944cb
PMF
1163 have_listener = 0;
1164 create_listener();
99b72dc0
PMF
1165 init_socket();
1166 ltt_trace_setup("auto");
1167 result = ltt_trace_set_type("auto", "ustrelay");
1168 if(result < 0) {
1169 ERR("ltt_trace_set_type failed");
036db133 1170 return;
99b72dc0
PMF
1171 }
1172
1173 ltt_trace_alloc("auto");
1174 ltt_trace_start("auto");
ad45e833 1175 inform_consumer_daemon("auto");
1e2944cb
PMF
1176}
1177
This page took 0.122107 seconds and 4 git commands to generate.