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