libust: change some licences to LGPL
[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>
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
68c1021b
PMF
107void do_command(struct tracecmd *cmd)
108{
109}
110
26cc7017
PMF
111/* This needs to be called whenever a new thread is created. It notifies
112 * liburcu of the new thread.
113 */
114
115void ust_register_thread(void)
68c1021b 116{
26cc7017 117 rcu_register_thread();
68c1021b
PMF
118}
119
98963de4
PMF
120int fd_notif = -1;
121void notif_cb(void)
122{
123 int result;
124 struct trctl_msg msg;
125
126 /* FIXME: fd_notif should probably be protected by a spinlock */
127
128 if(fd_notif == -1)
129 return;
130
131 msg.type = MSG_NOTIF;
132 msg.size = sizeof(msg.type);
133
134 /* FIXME: don't block here */
135 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
136 if(result == -1) {
137 PERROR("write");
138 return;
139 }
140}
141
872037bb 142static void inform_consumer_daemon(void)
d0b5f2b9 143{
3847c3ba
PMF
144 ustcomm_request_consumer(getpid(), "metadata");
145 ustcomm_request_consumer(getpid(), "ust");
d0b5f2b9 146}
fbd8191b 147
3a7b90de
PMF
148void process_blocked_consumers(void)
149{
150 int n_fds = 0;
151 struct pollfd *fds;
152 struct blocked_consumer *bc;
153 int idx = 0;
154 char inbuf;
155 int result;
156
157 list_for_each_entry(bc, &blocked_consumers, list) {
158 n_fds++;
159 }
160
161 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
162 if(fds == NULL) {
163 ERR("malloc returned NULL");
164 return;
165 }
166
167 list_for_each_entry(bc, &blocked_consumers, list) {
168 fds[idx].fd = bc->fd_producer;
169 fds[idx].events = POLLIN;
170 bc->tmp_poll_idx = idx;
171 idx++;
172 }
173
69ba0156
PMF
174 while((result = poll(fds, n_fds, 0)) == -1 && errno == EINTR)
175 /* nothing */;
3a7b90de
PMF
176 if(result == -1) {
177 PERROR("poll");
872037bb 178 return;
3a7b90de
PMF
179 }
180
181 list_for_each_entry(bc, &blocked_consumers, list) {
182 if(fds[bc->tmp_poll_idx].revents) {
183 long consumed_old = 0;
184 char *reply;
185
186 result = read(bc->fd_producer, &inbuf, 1);
187 if(result == -1) {
188 PERROR("read");
189 continue;
190 }
191 if(result == 0) {
192 DBG("PRODUCER END");
193
194 close(bc->fd_producer);
195
769d0157 196 list_del(&bc->list);
3a7b90de
PMF
197
198 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
199 if(result < 0) {
200 ERR("ustcomm_send_reply failed");
201 continue;
202 }
203
204 continue;
205 }
206
207 result = ltt_do_get_subbuf(bc->rbuf, bc->lttbuf, &consumed_old);
208 if(result == -EAGAIN) {
209 WARN("missed buffer?");
210 continue;
211 }
212 else if(result < 0) {
213 DBG("ltt_do_get_subbuf: error: %s", strerror(-result));
214 }
215 asprintf(&reply, "%s %ld", "OK", consumed_old);
216 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
217 if(result < 0) {
218 ERR("ustcomm_send_reply failed");
219 free(reply);
220 continue;
221 }
222 free(reply);
223
769d0157 224 list_del(&bc->list);
3a7b90de
PMF
225 }
226 }
227
228}
229
872037bb 230void *listener_main(void *p)
98963de4
PMF
231{
232 int result;
233
26cc7017
PMF
234 ust_register_thread();
235
b0540e11
PMF
236 DBG("LISTENER");
237
98963de4 238 for(;;) {
aafb1650
PMF
239 char trace_name[] = "auto";
240 char trace_type[] = "ustrelay";
d0b5f2b9
PMF
241 char *recvbuf;
242 int len;
b02e31e5 243 struct ustcomm_source src;
98963de4 244
3a7b90de
PMF
245 process_blocked_consumers();
246
247 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
248 if(result < 0) {
d0b5f2b9
PMF
249 WARN("error in ustcomm_app_recv_message");
250 continue;
251 }
3a7b90de
PMF
252 else if(result == 0) {
253 /* no message */
254 continue;
255 }
98963de4 256
d0b5f2b9
PMF
257 DBG("received a message! it's: %s\n", recvbuf);
258 len = strlen(recvbuf);
98963de4 259
d0b5f2b9 260 if(!strcmp(recvbuf, "print_markers")) {
52c51a47
PMF
261 print_markers(stderr);
262 }
263 else if(!strcmp(recvbuf, "list_markers")) {
264 char *ptr;
265 size_t size;
266 FILE *fp;
267
268 fp = open_memstream(&ptr, &size);
269 print_markers(fp);
270 fclose(fp);
271
272 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
273
274 free(ptr);
275 }
276 else if(!strcmp(recvbuf, "start")) {
277 /* start is an operation that setups the trace, allocates it and starts it */
278 result = ltt_trace_setup(trace_name);
279 if(result < 0) {
280 ERR("ltt_trace_setup failed");
872037bb 281 return (void *)1;
52c51a47
PMF
282 }
283
284 result = ltt_trace_set_type(trace_name, trace_type);
285 if(result < 0) {
286 ERR("ltt_trace_set_type failed");
872037bb 287 return (void *)1;
52c51a47
PMF
288 }
289
290 result = ltt_trace_alloc(trace_name);
291 if(result < 0) {
292 ERR("ltt_trace_alloc failed");
872037bb 293 return (void *)1;
52c51a47
PMF
294 }
295
296 inform_consumer_daemon();
297
298 result = ltt_trace_start(trace_name);
299 if(result < 0) {
300 ERR("ltt_trace_start failed");
301 continue;
302 }
d0b5f2b9
PMF
303 }
304 else if(!strcmp(recvbuf, "trace_setup")) {
305 DBG("trace setup");
fbd8191b 306
d0b5f2b9
PMF
307 result = ltt_trace_setup(trace_name);
308 if(result < 0) {
309 ERR("ltt_trace_setup failed");
872037bb 310 return (void *)1;
fbd8191b 311 }
d0b5f2b9
PMF
312
313 result = ltt_trace_set_type(trace_name, trace_type);
314 if(result < 0) {
315 ERR("ltt_trace_set_type failed");
872037bb 316 return (void *)1;
fbd8191b 317 }
d0b5f2b9
PMF
318 }
319 else if(!strcmp(recvbuf, "trace_alloc")) {
320 DBG("trace alloc");
321
322 result = ltt_trace_alloc(trace_name);
323 if(result < 0) {
324 ERR("ltt_trace_alloc failed");
872037bb 325 return (void *)1;
fbd8191b 326 }
d0b5f2b9
PMF
327 }
328 else if(!strcmp(recvbuf, "trace_start")) {
329 DBG("trace start");
330
331 result = ltt_trace_start(trace_name);
332 if(result < 0) {
333 ERR("ltt_trace_start failed");
334 continue;
fbd8191b 335 }
d0b5f2b9
PMF
336 }
337 else if(!strcmp(recvbuf, "trace_stop")) {
338 DBG("trace stop");
339
340 result = ltt_trace_stop(trace_name);
341 if(result < 0) {
342 ERR("ltt_trace_stop failed");
872037bb 343 return (void *)1;
aafb1650 344 }
d0b5f2b9
PMF
345 }
346 else if(!strcmp(recvbuf, "trace_destroy")) {
aafb1650 347
d0b5f2b9 348 DBG("trace destroy");
aafb1650 349
d0b5f2b9
PMF
350 result = ltt_trace_destroy(trace_name);
351 if(result < 0) {
352 ERR("ltt_trace_destroy failed");
872037bb 353 return (void *)1;
fbd8191b 354 }
98963de4 355 }
b02e31e5 356 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
3847c3ba
PMF
357 struct ltt_trace_struct *trace;
358 char trace_name[] = "auto";
359 int i;
811e4b93 360 char *channel_name;
3847c3ba
PMF
361
362 DBG("get_shmid");
363
811e4b93
PMF
364 channel_name = nth_token(recvbuf, 1);
365 if(channel_name == NULL) {
366 ERR("get_shmid: cannot parse channel");
367 goto next_cmd;
368 }
369
3847c3ba
PMF
370 ltt_lock_traces();
371 trace = _ltt_trace_find(trace_name);
372 ltt_unlock_traces();
373
374 if(trace == NULL) {
63fe14e5 375 ERR("cannot find trace!");
872037bb 376 return (void *)1;
3847c3ba
PMF
377 }
378
379 for(i=0; i<trace->nr_channels; i++) {
380 struct rchan *rchan = trace->channels[i].trans_channel_data;
381 struct rchan_buf *rbuf = rchan->buf;
8cefc145 382 struct ltt_channel_struct *ltt_channel = (struct ltt_channel_struct *)rchan->private_data;
3847c3ba 383
811e4b93
PMF
384 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
385 char *reply;
386
387 DBG("the shmid for the requested channel is %d", rbuf->shmid);
8cefc145
PMF
388 DBG("the shmid for its buffer structure is %d", ltt_channel->buf_shmid);
389 asprintf(&reply, "%d %d", rbuf->shmid, ltt_channel->buf_shmid);
811e4b93
PMF
390
391 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
392 if(result) {
393 ERR("listener: get_shmid: ustcomm_send_reply failed");
394 goto next_cmd;
395 }
396
397 free(reply);
398
399 break;
400 }
401 }
402 }
403 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
404 struct ltt_trace_struct *trace;
405 char trace_name[] = "auto";
406 int i;
407 char *channel_name;
408
409 DBG("get_n_subbufs");
410
411 channel_name = nth_token(recvbuf, 1);
412 if(channel_name == NULL) {
413 ERR("get_n_subbufs: cannot parse channel");
414 goto next_cmd;
415 }
416
417 ltt_lock_traces();
418 trace = _ltt_trace_find(trace_name);
419 ltt_unlock_traces();
420
421 if(trace == NULL) {
63fe14e5 422 ERR("cannot find trace!");
872037bb 423 return (void *)1;
811e4b93
PMF
424 }
425
426 for(i=0; i<trace->nr_channels; i++) {
427 struct rchan *rchan = trace->channels[i].trans_channel_data;
428
429 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
430 char *reply;
431
872037bb
PMF
432 DBG("the n_subbufs for the requested channel is %zd", rchan->n_subbufs);
433 asprintf(&reply, "%zd", rchan->n_subbufs);
811e4b93
PMF
434
435 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
436 if(result) {
437 ERR("listener: get_n_subbufs: ustcomm_send_reply failed");
438 goto next_cmd;
439 }
440
441 free(reply);
442
443 break;
444 }
445 }
446 }
447 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
448 struct ltt_trace_struct *trace;
449 char trace_name[] = "auto";
450 int i;
451 char *channel_name;
452
453 DBG("get_subbuf_size");
454
455 channel_name = nth_token(recvbuf, 1);
456 if(channel_name == NULL) {
457 ERR("get_subbuf_size: cannot parse channel");
458 goto next_cmd;
459 }
460
461 ltt_lock_traces();
462 trace = _ltt_trace_find(trace_name);
463 ltt_unlock_traces();
464
465 if(trace == NULL) {
63fe14e5 466 ERR("cannot find trace!");
872037bb 467 return (void *)1;
811e4b93
PMF
468 }
469
470 for(i=0; i<trace->nr_channels; i++) {
471 struct rchan *rchan = trace->channels[i].trans_channel_data;
472
473 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
474 char *reply;
475
872037bb
PMF
476 DBG("the subbuf_size for the requested channel is %zd", rchan->subbuf_size);
477 asprintf(&reply, "%zd", rchan->subbuf_size);
811e4b93
PMF
478
479 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
480 if(result) {
481 ERR("listener: get_subbuf_size: ustcomm_send_reply failed");
482 goto next_cmd;
483 }
484
485 free(reply);
3847c3ba 486
811e4b93
PMF
487 break;
488 }
3847c3ba
PMF
489 }
490 }
b02e31e5
PMF
491 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
492 char *libfile;
493
494 libfile = nth_token(recvbuf, 1);
495
496 DBG("load_probe_lib loading %s", libfile);
497 }
688760ef
PMF
498 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
499 struct ltt_trace_struct *trace;
500 char trace_name[] = "auto";
501 int i;
502 char *channel_name;
503
504 DBG("get_subbuf");
505
506 channel_name = nth_token(recvbuf, 1);
507 if(channel_name == NULL) {
508 ERR("get_subbuf: cannot parse channel");
509 goto next_cmd;
510 }
511
512 ltt_lock_traces();
513 trace = _ltt_trace_find(trace_name);
514 ltt_unlock_traces();
515
516 if(trace == NULL) {
63fe14e5 517 ERR("cannot find trace!");
872037bb 518 return (void *)1;
688760ef
PMF
519 }
520
521 for(i=0; i<trace->nr_channels; i++) {
522 struct rchan *rchan = trace->channels[i].trans_channel_data;
523
524 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
525 struct rchan_buf *rbuf = rchan->buf;
526 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
3a7b90de 527 struct blocked_consumer *bc;
688760ef 528
3a7b90de
PMF
529 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
530 if(bc == NULL) {
531 ERR("malloc returned NULL");
688760ef
PMF
532 goto next_cmd;
533 }
3a7b90de
PMF
534 bc->fd_consumer = src.fd;
535 bc->fd_producer = lttbuf->data_ready_fd_read;
536 bc->rbuf = rbuf;
537 bc->lttbuf = lttbuf;
538 bc->src = src;
539 bc->server = ustcomm_app.server;
688760ef 540
3a7b90de 541 list_add(&bc->list, &blocked_consumers);
688760ef
PMF
542
543 break;
544 }
545 }
546 }
547 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
548 struct ltt_trace_struct *trace;
549 char trace_name[] = "auto";
550 int i;
551 char *channel_name;
552 long consumed_old;
553 char *consumed_old_str;
554 char *endptr;
555
556 DBG("put_subbuf");
557
558 channel_name = strdup_malloc(nth_token(recvbuf, 1));
559 if(channel_name == NULL) {
560 ERR("put_subbuf_size: cannot parse channel");
561 goto next_cmd;
562 }
563
564 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
565 if(consumed_old_str == NULL) {
566 ERR("put_subbuf: cannot parse consumed_old");
567 goto next_cmd;
568 }
569 consumed_old = strtol(consumed_old_str, &endptr, 10);
570 if(*endptr != '\0') {
571 ERR("put_subbuf: invalid value for consumed_old");
572 goto next_cmd;
573 }
574
575 ltt_lock_traces();
576 trace = _ltt_trace_find(trace_name);
577 ltt_unlock_traces();
578
579 if(trace == NULL) {
63fe14e5 580 ERR("cannot find trace!");
872037bb 581 return (void *)1;
688760ef
PMF
582 }
583
584 for(i=0; i<trace->nr_channels; i++) {
585 struct rchan *rchan = trace->channels[i].trans_channel_data;
586
587 if(!strcmp(trace->channels[i].channel_name, channel_name)) {
588 struct rchan_buf *rbuf = rchan->buf;
589 struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
590 char *reply;
591 long consumed_old=0;
592
593 result = ltt_do_put_subbuf(rbuf, lttbuf, consumed_old);
594 if(result < 0) {
0a58610f 595 WARN("ltt_do_put_subbuf: error (subbuf=%s)", channel_name);
872037bb 596 asprintf(&reply, "%s", "ERROR");
688760ef
PMF
597 }
598 else {
0a58610f 599 DBG("ltt_do_put_subbuf: success (subbuf=%s)", channel_name);
872037bb 600 asprintf(&reply, "%s", "OK");
688760ef 601 }
688760ef
PMF
602
603 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
604 if(result) {
605 ERR("listener: put_subbuf: ustcomm_send_reply failed");
606 goto next_cmd;
607 }
608
609 free(reply);
610
611 break;
612 }
613 }
614
615 free(channel_name);
616 free(consumed_old_str);
617 }
52c51a47
PMF
618 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
619 char *channel_slash_name = nth_token(recvbuf, 1);
620 char channel_name[256]="";
621 char marker_name[256]="";
52c51a47
PMF
622
623 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
624
625 if(channel_name == NULL || marker_name == NULL) {
626 WARN("invalid marker name");
627 goto next_cmd;
628 }
629 printf("%s %s\n", channel_name, marker_name);
630
631 result = ltt_marker_connect(channel_name, marker_name, "default");
632 if(result < 0) {
633 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
634 }
635 }
636 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
637 char *channel_slash_name = nth_token(recvbuf, 1);
638 char *marker_name;
639 char *channel_name;
52c51a47
PMF
640
641 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
642
643 if(marker_name == NULL) {
644 }
645 printf("%s %s\n", channel_name, marker_name);
646
647 result = ltt_marker_disconnect(channel_name, marker_name, "default");
648 if(result < 0) {
649 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
650 }
651 }
3a7b90de
PMF
652// else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
653// struct ltt_trace_struct *trace;
654// char trace_name[] = "auto";
655// int i;
656// char *channel_name;
657//
658// DBG("get_notifications");
659//
660// channel_name = strdup_malloc(nth_token(recvbuf, 1));
661// if(channel_name == NULL) {
662// ERR("put_subbuf_size: cannot parse channel");
663// goto next_cmd;
664// }
665//
666// ltt_lock_traces();
667// trace = _ltt_trace_find(trace_name);
668// ltt_unlock_traces();
669//
670// if(trace == NULL) {
63fe14e5 671// ERR("cannot find trace!");
872037bb 672// return (void *)1;
3a7b90de
PMF
673// }
674//
675// for(i=0; i<trace->nr_channels; i++) {
676// struct rchan *rchan = trace->channels[i].trans_channel_data;
677// int fd;
678//
679// if(!strcmp(trace->channels[i].channel_name, channel_name)) {
680// struct rchan_buf *rbuf = rchan->buf;
681// struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
682//
683// result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
684// if(result == -1) {
685// ERR("ustcomm_app_detach_client failed");
686// goto next_cmd;
687// }
688//
689// lttbuf->wake_consumer_arg = (void *) fd;
690//
691// smp_wmb();
692//
693// lttbuf->call_wake_consumer = 1;
694//
695// break;
696// }
697// }
698//
699// free(channel_name);
700// }
688760ef
PMF
701 else {
702 ERR("unable to parse message: %s", recvbuf);
703 }
d0b5f2b9 704
811e4b93 705 next_cmd:
d0b5f2b9 706 free(recvbuf);
98963de4
PMF
707 }
708}
709
710void create_listener(void)
711{
9160b4e4 712#ifdef USE_CLONE
98963de4 713 static char listener_stack[16384];
9160b4e4 714#endif
98963de4 715
3847c3ba 716#ifdef USE_CLONE
fbd8191b 717 result = clone(listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
718 if(result == -1) {
719 perror("clone");
720 }
3847c3ba
PMF
721#else
722 pthread_t thread;
b0540e11 723
3847c3ba
PMF
724 pthread_create(&thread, NULL, listener_main, NULL);
725#endif
98963de4
PMF
726}
727
d0b5f2b9
PMF
728/* The signal handler itself. Signals must be setup so there cannot be
729 nested signals. */
68c1021b
PMF
730
731void sighandler(int sig)
732{
d0b5f2b9 733 static char have_listener = 0;
68c1021b 734 DBG("sighandler");
d0b5f2b9
PMF
735
736 if(!have_listener) {
737 create_listener();
738 have_listener = 1;
739 }
68c1021b
PMF
740}
741
742/* Called by the app signal handler to chain it to us. */
743
98963de4 744void chain_signal(void)
68c1021b
PMF
745{
746 sighandler(USTSIGNAL);
747}
748
98963de4 749static int init_socket(void)
68c1021b 750{
d0b5f2b9 751 return ustcomm_init_app(getpid(), &ustcomm_app);
68c1021b
PMF
752}
753
9160b4e4
PMF
754/* FIXME: reenable this to delete socket file. */
755
756#if 0
98963de4 757static void destroy_socket(void)
68c1021b 758{
9160b4e4
PMF
759 int result;
760
761 if(mysocketfile[0] == '\0')
762 return;
763
764 result = unlink(mysocketfile);
765 if(result == -1) {
766 PERROR("unlink");
767 }
68c1021b 768}
9160b4e4 769#endif
68c1021b 770
98963de4 771static int init_signal_handler(void)
68c1021b
PMF
772{
773 /* Attempt to handler SIGIO. If the main program wants to
774 * handle it, fine, it'll override us. They it'll have to
775 * use the chaining function.
776 */
777
778 int result;
779 struct sigaction act;
780
781 result = sigemptyset(&act.sa_mask);
782 if(result == -1) {
783 PERROR("sigemptyset");
784 return -1;
785 }
786
787 act.sa_handler = sighandler;
788 act.sa_flags = SA_RESTART;
789
790 /* Only defer ourselves. Also, try to restart interrupted
791 * syscalls to disturb the traced program as little as possible.
792 */
793 result = sigaction(SIGIO, &act, NULL);
794 if(result == -1) {
795 PERROR("sigaction");
796 return -1;
797 }
798
799 return 0;
800}
801
20b37a31 802static void auto_probe_connect(struct marker *m)
68c1021b
PMF
803{
804 int result;
805
20b37a31 806 result = ltt_marker_connect(m->channel, m->name, "default");
acbf228b
PMF
807 if(result && result != -EEXIST)
808 ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
20b37a31
PMF
809
810 DBG("just auto connected marker %s %s to probe default", m->channel, m->name);
811}
812
813static void __attribute__((constructor(101))) init0()
814{
26cc7017
PMF
815 /* Initialize RCU in case the constructor order is not good. */
816 urcu_init();
817
818 /* It is important to do this before events start to be generated. */
819 ust_register_thread();
820
20b37a31
PMF
821 DBG("UST_AUTOPROBE constructor");
822 if(getenv("UST_AUTOPROBE")) {
823 marker_set_new_marker_cb(auto_probe_connect);
824 }
825}
826
827static void __attribute__((constructor(1000))) init()
828{
829 int result;
830
831 DBG("UST_TRACE constructor");
832
3847c3ba
PMF
833 /* Must create socket before signal handler to prevent races.
834 */
835 result = init_socket();
836 if(result == -1) {
837 ERR("init_socket error");
838 return;
839 }
840 result = init_signal_handler();
841 if(result == -1) {
842 ERR("init_signal_handler error");
843 return;
844 }
68c1021b 845
4db647c5
PMF
846 if(getenv("UST_TRACE")) {
847 char trace_name[] = "auto";
848 char trace_type[] = "ustrelay";
849
850 DBG("starting early tracing");
851
852 /* Ensure marker control is initialized */
853 init_marker_control();
854
855 /* Ensure relay is initialized */
856 init_ustrelay_transport();
857
858 /* Ensure markers are initialized */
859 init_markers();
860
20b37a31
PMF
861 /* In case. */
862 ltt_channels_register("ust");
4db647c5
PMF
863
864 result = ltt_trace_setup(trace_name);
865 if(result < 0) {
866 ERR("ltt_trace_setup failed");
867 return;
868 }
869
870 result = ltt_trace_set_type(trace_name, trace_type);
871 if(result < 0) {
872 ERR("ltt_trace_set_type failed");
873 return;
874 }
875
876 result = ltt_trace_alloc(trace_name);
877 if(result < 0) {
878 ERR("ltt_trace_alloc failed");
879 return;
880 }
881
882 result = ltt_trace_start(trace_name);
883 if(result < 0) {
884 ERR("ltt_trace_start failed");
885 return;
886 }
3847c3ba 887 inform_consumer_daemon();
4db647c5
PMF
888 }
889
68c1021b
PMF
890
891 return;
892
893 /* should decrementally destroy stuff if error */
894
895}
896
897/* This is only called if we terminate normally, not with an unhandled signal,
898 * so we cannot rely on it. */
899
899b5967
PMF
900/* This destructor probably isn't needed, because ustd can do crash recovery. */
901#if 0
98963de4 902static void __attribute__((destructor)) fini()
68c1021b 903{
a584bc4e
PMF
904 int result;
905
906 /* if trace running, finish it */
907
908 DBG("destructor stopping traces");
909
910 result = ltt_trace_stop("auto");
911 if(result == -1) {
912 ERR("ltt_trace_stop error");
913 }
914
915 result = ltt_trace_destroy("auto");
916 if(result == -1) {
917 ERR("ltt_trace_destroy error");
918 }
919
68c1021b
PMF
920 destroy_socket();
921}
899b5967 922#endif
This page took 0.131559 seconds and 4 git commands to generate.