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