fix destruction to free all memory
[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 19#include <stdio.h>
909bc43f 20#include <stdlib.h>
68c1021b
PMF
21#include <stdint.h>
22#include <signal.h>
23#include <sys/types.h>
24#include <sys/socket.h>
25#include <sys/un.h>
98963de4 26#include <sched.h>
a584bc4e 27#include <fcntl.h>
3a7b90de 28#include <poll.h>
ef290fca 29#include <regex.h>
b102c2b0 30#include <urcu/uatomic_arch.h>
fbd8191b 31
93d0f2ea 32#include <ust/marker.h>
616ed36a 33#include <ust/tracectl.h>
c93858f1 34#include "tracer.h"
6af64c43 35#include "usterr.h"
d0b5f2b9 36#include "ustcomm.h"
b73a4c47 37#include "buffers.h"
9160b4e4 38#include "marker-control.h"
fbd8191b 39
b02e31e5 40//#define USE_CLONE
3847c3ba 41
68c1021b
PMF
42#define USTSIGNAL SIGIO
43
98963de4
PMF
44#define MAX_MSG_SIZE (100)
45#define MSG_NOTIF 1
46#define MSG_REGISTER_NOTIF 2
47
a584bc4e
PMF
48char consumer_stack[10000];
49
ed1317e7
PMF
50/* This should only be accessed by the constructor, before the creation
51 * of the listener, and then only by the listener.
52 */
53s64 pidunique = -1LL;
54
3a7b90de
PMF
55struct list_head blocked_consumers = LIST_HEAD_INIT(blocked_consumers);
56
d0b5f2b9
PMF
57static struct ustcomm_app ustcomm_app;
58
68c1021b
PMF
59struct tracecmd { /* no padding */
60 uint32_t size;
61 uint16_t command;
62};
63
f293009f
PMF
64/* volatile because shared between the listener and the main thread */
65volatile sig_atomic_t buffers_to_export = 0;
66
98963de4
PMF
67struct trctl_msg {
68 /* size: the size of all the fields except size itself */
69 uint32_t size;
70 uint16_t type;
71 /* Only the necessary part of the payload is transferred. It
72 * may even be none of it.
73 */
74 char payload[94];
75};
68c1021b 76
a584bc4e
PMF
77struct consumer_channel {
78 int fd;
79 struct ltt_channel_struct *chan;
80};
81
3a7b90de
PMF
82struct blocked_consumer {
83 int fd_consumer;
84 int fd_producer;
85 int tmp_poll_idx;
86
87 /* args to ustcomm_send_reply */
88 struct ustcomm_server server;
89 struct ustcomm_source src;
90
b73a4c47 91 /* args to ust_buffers_get_subbuf */
b5b073e2 92 struct ust_buffer *buf;
3a7b90de
PMF
93
94 struct list_head list;
95};
96
ed1317e7
PMF
97static long long make_pidunique(void)
98{
99 s64 retval;
100 struct timeval tv;
101
102 gettimeofday(&tv, NULL);
103
104 retval = tv.tv_sec;
105 retval <<= 32;
106 retval |= tv.tv_usec;
107
108 return retval;
109}
110
52c51a47 111static void print_markers(FILE *fp)
fbd8191b
PMF
112{
113 struct marker_iter iter;
114
d0b5f2b9 115 lock_markers();
fbd8191b
PMF
116 marker_iter_reset(&iter);
117 marker_iter_start(&iter);
118
119 while(iter.marker) {
3ea1e2fc 120 fprintf(fp, "marker: %s/%s %d \"%s\" %p\n", iter.marker->channel, iter.marker->name, (int)imv_read(iter.marker->state), iter.marker->format, iter.marker->location);
fbd8191b
PMF
121 marker_iter_next(&iter);
122 }
d0b5f2b9 123 unlock_markers();
fbd8191b
PMF
124}
125
4440ebcb 126static int init_socket(void);
68c1021b 127
98963de4
PMF
128int fd_notif = -1;
129void notif_cb(void)
130{
131 int result;
132 struct trctl_msg msg;
133
134 /* FIXME: fd_notif should probably be protected by a spinlock */
135
136 if(fd_notif == -1)
137 return;
138
139 msg.type = MSG_NOTIF;
140 msg.size = sizeof(msg.type);
141
142 /* FIXME: don't block here */
143 result = write(fd_notif, &msg, msg.size+sizeof(msg.size));
144 if(result == -1) {
145 PERROR("write");
146 return;
147 }
148}
149
ad45e833
PMF
150/* Ask the daemon to collect a trace called trace_name and being
151 * produced by this pid.
152 *
153 * The trace must be at least allocated. (It can also be started.)
154 * This is because _ltt_trace_find is used.
155 */
156
157static void inform_consumer_daemon(const char *trace_name)
d0b5f2b9 158{
204141ee 159 int i,j;
b73a4c47 160 struct ust_trace *trace;
ad45e833
PMF
161 pid_t pid = getpid();
162 int result;
163
164 ltt_lock_traces();
165
166 trace = _ltt_trace_find(trace_name);
167 if(trace == NULL) {
168 WARN("inform_consumer_daemon: could not find trace \"%s\"; it is probably already destroyed", trace_name);
169 goto finish;
170 }
171
172 for(i=0; i < trace->nr_channels; i++) {
204141ee
PMF
173 /* iterate on all cpus */
174 for(j=0; j<trace->channels[i].n_cpus; j++) {
175 char *buf;
176 asprintf(&buf, "%s_%d", trace->channels[i].channel_name, j);
177 result = ustcomm_request_consumer(pid, buf);
178 if(result == -1) {
179 WARN("Failed to request collection for channel %s. Is the daemon available?", trace->channels[i].channel_name);
180 /* continue even if fail */
181 }
182 free(buf);
183 buffers_to_export++;
ad45e833
PMF
184 }
185 }
186
187 finish:
188 ltt_unlock_traces();
d0b5f2b9 189}
fbd8191b 190
3a7b90de
PMF
191void process_blocked_consumers(void)
192{
193 int n_fds = 0;
194 struct pollfd *fds;
195 struct blocked_consumer *bc;
196 int idx = 0;
197 char inbuf;
198 int result;
199
200 list_for_each_entry(bc, &blocked_consumers, list) {
201 n_fds++;
202 }
203
204 fds = (struct pollfd *) malloc(n_fds * sizeof(struct pollfd));
205 if(fds == NULL) {
206 ERR("malloc returned NULL");
207 return;
208 }
209
210 list_for_each_entry(bc, &blocked_consumers, list) {
211 fds[idx].fd = bc->fd_producer;
212 fds[idx].events = POLLIN;
213 bc->tmp_poll_idx = idx;
214 idx++;
215 }
216
69ba0156
PMF
217 while((result = poll(fds, n_fds, 0)) == -1 && errno == EINTR)
218 /* nothing */;
3a7b90de
PMF
219 if(result == -1) {
220 PERROR("poll");
872037bb 221 return;
3a7b90de
PMF
222 }
223
224 list_for_each_entry(bc, &blocked_consumers, list) {
225 if(fds[bc->tmp_poll_idx].revents) {
226 long consumed_old = 0;
227 char *reply;
228
229 result = read(bc->fd_producer, &inbuf, 1);
230 if(result == -1) {
231 PERROR("read");
232 continue;
233 }
234 if(result == 0) {
235 DBG("PRODUCER END");
236
237 close(bc->fd_producer);
238
769d0157 239 list_del(&bc->list);
3a7b90de
PMF
240
241 result = ustcomm_send_reply(&bc->server, "END", &bc->src);
242 if(result < 0) {
243 ERR("ustcomm_send_reply failed");
244 continue;
245 }
246
247 continue;
248 }
249
b73a4c47 250 result = ust_buffers_get_subbuf(bc->buf, &consumed_old);
3a7b90de
PMF
251 if(result == -EAGAIN) {
252 WARN("missed buffer?");
253 continue;
254 }
255 else if(result < 0) {
b73a4c47 256 DBG("ust_buffers_get_subbuf: error: %s", strerror(-result));
3a7b90de
PMF
257 }
258 asprintf(&reply, "%s %ld", "OK", consumed_old);
259 result = ustcomm_send_reply(&bc->server, reply, &bc->src);
260 if(result < 0) {
261 ERR("ustcomm_send_reply failed");
262 free(reply);
263 continue;
264 }
265 free(reply);
266
769d0157 267 list_del(&bc->list);
3a7b90de
PMF
268 }
269 }
270
271}
272
204141ee
PMF
273void seperate_channel_cpu(const char *channel_and_cpu, char **channel, int *cpu)
274{
275 const char *sep;
276
277 sep = rindex(channel_and_cpu, '_');
278 if(sep == NULL) {
279 *cpu = -1;
280 sep = channel_and_cpu + strlen(channel_and_cpu);
281 }
282 else {
283 *cpu = atoi(sep+1);
284 }
285
286 asprintf(channel, "%.*s", (int)(sep-channel_and_cpu), channel_and_cpu);
287}
288
289static int do_cmd_get_shmid(const char *recvbuf, struct ustcomm_source *src)
290{
291 int retval = 0;
b73a4c47 292 struct ust_trace *trace;
204141ee
PMF
293 char trace_name[] = "auto";
294 int i;
295 char *channel_and_cpu;
296 int found = 0;
297 int result;
298 char *ch_name;
299 int ch_cpu;
300
301 DBG("get_shmid");
302
303 channel_and_cpu = nth_token(recvbuf, 1);
304 if(channel_and_cpu == NULL) {
27e84572 305 ERR("cannot parse channel");
204141ee
PMF
306 goto end;
307 }
308
309 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
310 if(ch_cpu == -1) {
27e84572 311 ERR("problem parsing channel name");
204141ee
PMF
312 goto free_short_chan_name;
313 }
314
315 ltt_lock_traces();
316 trace = _ltt_trace_find(trace_name);
317 ltt_unlock_traces();
318
319 if(trace == NULL) {
320 ERR("cannot find trace!");
321 retval = -1;
322 goto free_short_chan_name;
323 }
324
325 for(i=0; i<trace->nr_channels; i++) {
326 struct ust_channel *channel = &trace->channels[i];
327 struct ust_buffer *buf = channel->buf[ch_cpu];
328
329 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
330 char *reply;
331
332// DBG("the shmid for the requested channel is %d", buf->shmid);
333// DBG("the shmid for its buffer structure is %d", channel->buf_struct_shmids);
334 asprintf(&reply, "%d %d", buf->shmid, channel->buf_struct_shmids[ch_cpu]);
335
336 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
337 if(result) {
27e84572 338 ERR("ustcomm_send_reply failed");
204141ee
PMF
339 free(reply);
340 retval = -1;
341 goto free_short_chan_name;
342 }
343
344 free(reply);
345
346 found = 1;
347 break;
348 }
349 }
350
d5adede0 351 if(!found) {
27e84572 352 ERR("channel not found (%s)", channel_and_cpu);
204141ee
PMF
353 }
354
355 free_short_chan_name:
356 free(ch_name);
357
358 end:
359 return retval;
360}
361
362static int do_cmd_get_n_subbufs(const char *recvbuf, struct ustcomm_source *src)
363{
364 int retval = 0;
b73a4c47 365 struct ust_trace *trace;
204141ee
PMF
366 char trace_name[] = "auto";
367 int i;
368 char *channel_and_cpu;
369 int found = 0;
370 int result;
371 char *ch_name;
372 int ch_cpu;
373
374 DBG("get_n_subbufs");
375
376 channel_and_cpu = nth_token(recvbuf, 1);
377 if(channel_and_cpu == NULL) {
27e84572 378 ERR("cannot parse channel");
204141ee
PMF
379 goto end;
380 }
381
382 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
383 if(ch_cpu == -1) {
27e84572 384 ERR("problem parsing channel name");
204141ee
PMF
385 goto free_short_chan_name;
386 }
387
388 ltt_lock_traces();
389 trace = _ltt_trace_find(trace_name);
390 ltt_unlock_traces();
391
392 if(trace == NULL) {
393 ERR("cannot find trace!");
394 retval = -1;
395 goto free_short_chan_name;
396 }
397
398 for(i=0; i<trace->nr_channels; i++) {
399 struct ust_channel *channel = &trace->channels[i];
400
401 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
402 char *reply;
403
404 DBG("the n_subbufs for the requested channel is %d", channel->subbuf_cnt);
405 asprintf(&reply, "%d", channel->subbuf_cnt);
406
407 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
408 if(result) {
27e84572 409 ERR("ustcomm_send_reply failed");
204141ee
PMF
410 free(reply);
411 retval = -1;
412 goto free_short_chan_name;
413 }
414
415 free(reply);
416 found = 1;
417 break;
418 }
419 }
420 if(found == 0) {
27e84572 421 ERR("unable to find channel");
204141ee
PMF
422 }
423
424 free_short_chan_name:
425 free(ch_name);
426
427 end:
428 return retval;
429}
430
431static int do_cmd_get_subbuf_size(const char *recvbuf, struct ustcomm_source *src)
432{
433 int retval = 0;
b73a4c47 434 struct ust_trace *trace;
204141ee
PMF
435 char trace_name[] = "auto";
436 int i;
437 char *channel_and_cpu;
438 int found = 0;
439 int result;
440 char *ch_name;
441 int ch_cpu;
442
443 DBG("get_subbuf_size");
444
445 channel_and_cpu = nth_token(recvbuf, 1);
446 if(channel_and_cpu == NULL) {
27e84572 447 ERR("cannot parse channel");
204141ee
PMF
448 goto end;
449 }
450
451 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
452 if(ch_cpu == -1) {
27e84572 453 ERR("problem parsing channel name");
204141ee
PMF
454 goto free_short_chan_name;
455 }
456
457 ltt_lock_traces();
458 trace = _ltt_trace_find(trace_name);
459 ltt_unlock_traces();
460
461 if(trace == NULL) {
462 ERR("cannot find trace!");
463 retval = -1;
464 goto free_short_chan_name;
465 }
466
467 for(i=0; i<trace->nr_channels; i++) {
468 struct ust_channel *channel = &trace->channels[i];
469
470 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
471 char *reply;
472
473 DBG("the subbuf_size for the requested channel is %zd", channel->subbuf_size);
474 asprintf(&reply, "%zd", channel->subbuf_size);
475
476 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
477 if(result) {
27e84572 478 ERR("ustcomm_send_reply failed");
204141ee
PMF
479 free(reply);
480 retval = -1;
481 goto free_short_chan_name;
482 }
483
484 free(reply);
485 found = 1;
486 break;
487 }
488 }
489 if(found == 0) {
27e84572 490 ERR("unable to find channel");
204141ee
PMF
491 }
492
493 free_short_chan_name:
494 free(ch_name);
495
496 end:
497 return retval;
498}
499
e43efba9 500static unsigned int poweroftwo(unsigned int x)
763f41e5
DS
501{
502 unsigned int power2 = 1;
503 unsigned int hardcoded = 2147483648; /* FIX max 2^31 */
504
505 if (x < 2)
506 return 2;
507
508 while (power2 < x && power2 < hardcoded)
509 power2 *= 2;
510
511 return power2;
512}
513
514static int do_cmd_set_subbuf_size(const char *recvbuf, struct ustcomm_source *src)
515{
516 char *channel_slash_size;
517 char ch_name[256]="";
518 unsigned int size, power;
519 int retval = 0;
520 struct ust_trace *trace;
521 char trace_name[] = "auto";
522 int i;
523 int found = 0;
524
525 DBG("set_subbuf_size");
526
527 channel_slash_size = nth_token(recvbuf, 1);
528 sscanf(channel_slash_size, "%255[^/]/%u", ch_name, &size);
529
530 if(ch_name == NULL) {
531 ERR("cannot parse channel");
532 goto end;
533 }
534
535 power = poweroftwo(size);
536 if (power != size)
537 WARN("using the next 2^n = %u\n", power);
538
539 ltt_lock_traces();
540 trace = _ltt_trace_find_setup(trace_name);
541 if(trace == NULL) {
542 ERR("cannot find trace!");
763f41e5
DS
543 retval = -1;
544 goto end;
545 }
546
547 for(i = 0; i < trace->nr_channels; i++) {
548 struct ust_channel *channel = &trace->channels[i];
549
550 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
551
552 channel->subbuf_size = power;
553 DBG("the set_subbuf_size for the requested channel is %zd", channel->subbuf_size);
554
555 found = 1;
556 break;
557 }
558 }
559 if(found == 0) {
560 ERR("unable to find channel");
561 }
562
763f41e5 563 end:
86dd0ebc 564 ltt_unlock_traces();
763f41e5
DS
565 return retval;
566}
567
568static int do_cmd_set_subbuf_num(const char *recvbuf, struct ustcomm_source *src)
569{
570 char *channel_slash_num;
571 char ch_name[256]="";
572 unsigned int num;
573 int retval = 0;
574 struct ust_trace *trace;
575 char trace_name[] = "auto";
576 int i;
577 int found = 0;
578
579 DBG("set_subbuf_num");
580
581 channel_slash_num = nth_token(recvbuf, 1);
582 sscanf(channel_slash_num, "%255[^/]/%u", ch_name, &num);
583
584 if(ch_name == NULL) {
585 ERR("cannot parse channel");
586 goto end;
587 }
588 if (num < 2) {
589 ERR("subbuffer count should be greater than 2");
590 goto end;
591 }
592
593 ltt_lock_traces();
594 trace = _ltt_trace_find_setup(trace_name);
595 if(trace == NULL) {
596 ERR("cannot find trace!");
763f41e5
DS
597 retval = -1;
598 goto end;
599 }
600
601 for(i = 0; i < trace->nr_channels; i++) {
602 struct ust_channel *channel = &trace->channels[i];
603
604 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
605
606 channel->subbuf_cnt = num;
607 DBG("the set_subbuf_cnt for the requested channel is %zd", channel->subbuf_cnt);
608
609 found = 1;
610 break;
611 }
612 }
613 if(found == 0) {
614 ERR("unable to find channel");
615 }
616
763f41e5 617 end:
86dd0ebc 618 ltt_unlock_traces();
763f41e5
DS
619 return retval;
620}
621
204141ee
PMF
622static int do_cmd_get_subbuffer(const char *recvbuf, struct ustcomm_source *src)
623{
624 int retval = 0;
b73a4c47 625 struct ust_trace *trace;
204141ee
PMF
626 char trace_name[] = "auto";
627 int i;
628 char *channel_and_cpu;
629 int found = 0;
630 char *ch_name;
631 int ch_cpu;
632
633 DBG("get_subbuf");
634
635 channel_and_cpu = nth_token(recvbuf, 1);
636 if(channel_and_cpu == NULL) {
27e84572 637 ERR("cannot parse channel");
204141ee
PMF
638 goto end;
639 }
640
641 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
642 if(ch_cpu == -1) {
27e84572 643 ERR("problem parsing channel name");
204141ee
PMF
644 goto free_short_chan_name;
645 }
646
647 ltt_lock_traces();
648 trace = _ltt_trace_find(trace_name);
204141ee
PMF
649
650 if(trace == NULL) {
2ddb81a8
PMF
651 int result;
652
653 WARN("Cannot find trace. It was likely destroyed by the user.");
86dd0ebc 654 result = ustcomm_send_reply(&ustcomm_app.server, "NOTFOUND", src);
2ddb81a8
PMF
655 if(result) {
656 ERR("ustcomm_send_reply failed");
2ddb81a8 657 retval = -1;
86dd0ebc 658 goto unlock_traces;
2ddb81a8
PMF
659 }
660
86dd0ebc 661 goto unlock_traces;
204141ee
PMF
662 }
663
664 for(i=0; i<trace->nr_channels; i++) {
665 struct ust_channel *channel = &trace->channels[i];
666
667 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
668 struct ust_buffer *buf = channel->buf[ch_cpu];
669 struct blocked_consumer *bc;
670
671 found = 1;
672
673 bc = (struct blocked_consumer *) malloc(sizeof(struct blocked_consumer));
674 if(bc == NULL) {
675 ERR("malloc returned NULL");
86dd0ebc 676 goto unlock_traces;
204141ee
PMF
677 }
678 bc->fd_consumer = src->fd;
679 bc->fd_producer = buf->data_ready_fd_read;
680 bc->buf = buf;
681 bc->src = *src;
682 bc->server = ustcomm_app.server;
683
684 list_add(&bc->list, &blocked_consumers);
685
d5adede0
PMF
686 /* Being here is the proof the daemon has mapped the buffer in its
687 * memory. We may now decrement buffers_to_export.
688 */
b102c2b0 689 if(uatomic_read(&buf->consumed) == 0) {
d5adede0
PMF
690 DBG("decrementing buffers_to_export");
691 buffers_to_export--;
692 }
693
204141ee
PMF
694 break;
695 }
696 }
697 if(found == 0) {
27e84572 698 ERR("unable to find channel");
204141ee
PMF
699 }
700
86dd0ebc
PMF
701 unlock_traces:
702 ltt_unlock_traces();
703
204141ee
PMF
704 free_short_chan_name:
705 free(ch_name);
706
707 end:
708 return retval;
709}
710
711static int do_cmd_put_subbuffer(const char *recvbuf, struct ustcomm_source *src)
712{
713 int retval = 0;
b73a4c47 714 struct ust_trace *trace;
204141ee
PMF
715 char trace_name[] = "auto";
716 int i;
717 char *channel_and_cpu;
718 int found = 0;
719 int result;
720 char *ch_name;
721 int ch_cpu;
722 long consumed_old;
723 char *consumed_old_str;
724 char *endptr;
2ddb81a8 725 char *reply = NULL;
204141ee
PMF
726
727 DBG("put_subbuf");
728
729 channel_and_cpu = strdup_malloc(nth_token(recvbuf, 1));
730 if(channel_and_cpu == NULL) {
27e84572 731 ERR("cannot parse channel");
204141ee
PMF
732 retval = -1;
733 goto end;
734 }
735
736 consumed_old_str = strdup_malloc(nth_token(recvbuf, 2));
737 if(consumed_old_str == NULL) {
27e84572 738 ERR("cannot parse consumed_old");
204141ee
PMF
739 retval = -1;
740 goto free_channel_and_cpu;
741 }
742 consumed_old = strtol(consumed_old_str, &endptr, 10);
743 if(*endptr != '\0') {
27e84572 744 ERR("invalid value for consumed_old");
204141ee
PMF
745 retval = -1;
746 goto free_consumed_old_str;
747 }
748
749 seperate_channel_cpu(channel_and_cpu, &ch_name, &ch_cpu);
750 if(ch_cpu == -1) {
27e84572 751 ERR("problem parsing channel name");
204141ee
PMF
752 retval = -1;
753 goto free_short_chan_name;
754 }
755
756 ltt_lock_traces();
757 trace = _ltt_trace_find(trace_name);
204141ee
PMF
758
759 if(trace == NULL) {
2ddb81a8 760 WARN("Cannot find trace. It was likely destroyed by the user.");
86dd0ebc 761 result = ustcomm_send_reply(&ustcomm_app.server, "NOTFOUND", src);
2ddb81a8
PMF
762 if(result) {
763 ERR("ustcomm_send_reply failed");
2ddb81a8 764 retval = -1;
86dd0ebc 765 goto unlock_traces;
2ddb81a8
PMF
766 }
767
86dd0ebc 768 goto unlock_traces;
204141ee
PMF
769 }
770
771 for(i=0; i<trace->nr_channels; i++) {
772 struct ust_channel *channel = &trace->channels[i];
773
774 if(!strcmp(trace->channels[i].channel_name, ch_name)) {
775 struct ust_buffer *buf = channel->buf[ch_cpu];
204141ee
PMF
776
777 found = 1;
778
b73a4c47 779 result = ust_buffers_put_subbuf(buf, consumed_old);
204141ee 780 if(result < 0) {
b73a4c47 781 WARN("ust_buffers_put_subbuf: error (subbuf=%s)", channel_and_cpu);
204141ee
PMF
782 asprintf(&reply, "%s", "ERROR");
783 }
784 else {
b73a4c47 785 DBG("ust_buffers_put_subbuf: success (subbuf=%s)", channel_and_cpu);
204141ee
PMF
786 asprintf(&reply, "%s", "OK");
787 }
788
789 result = ustcomm_send_reply(&ustcomm_app.server, reply, src);
790 if(result) {
27e84572 791 ERR("ustcomm_send_reply failed");
204141ee
PMF
792 free(reply);
793 retval = -1;
86dd0ebc 794 goto unlock_traces;
204141ee
PMF
795 }
796
797 free(reply);
798 break;
799 }
800 }
801 if(found == 0) {
2ddb81a8 802 ERR("unable to find channel");
204141ee
PMF
803 }
804
86dd0ebc
PMF
805 unlock_traces:
806 ltt_unlock_traces();
204141ee
PMF
807 free_short_chan_name:
808 free(ch_name);
2ddb81a8
PMF
809 free_consumed_old_str:
810 free(consumed_old_str);
811 free_channel_and_cpu:
812 free(channel_and_cpu);
204141ee
PMF
813
814 end:
815 return retval;
816}
817
872037bb 818void *listener_main(void *p)
98963de4
PMF
819{
820 int result;
821
b0540e11
PMF
822 DBG("LISTENER");
823
98963de4 824 for(;;) {
aafb1650
PMF
825 char trace_name[] = "auto";
826 char trace_type[] = "ustrelay";
d0b5f2b9
PMF
827 char *recvbuf;
828 int len;
b02e31e5 829 struct ustcomm_source src;
98963de4 830
3a7b90de
PMF
831 process_blocked_consumers();
832
833 result = ustcomm_app_recv_message(&ustcomm_app, &recvbuf, &src, 5);
834 if(result < 0) {
d0b5f2b9
PMF
835 WARN("error in ustcomm_app_recv_message");
836 continue;
837 }
3a7b90de
PMF
838 else if(result == 0) {
839 /* no message */
840 continue;
841 }
98963de4 842
08230db7 843 DBG("received a message! it's: %s", recvbuf);
d0b5f2b9 844 len = strlen(recvbuf);
98963de4 845
d0b5f2b9 846 if(!strcmp(recvbuf, "print_markers")) {
52c51a47
PMF
847 print_markers(stderr);
848 }
849 else if(!strcmp(recvbuf, "list_markers")) {
850 char *ptr;
851 size_t size;
852 FILE *fp;
853
854 fp = open_memstream(&ptr, &size);
855 print_markers(fp);
856 fclose(fp);
857
858 result = ustcomm_send_reply(&ustcomm_app.server, ptr, &src);
859
860 free(ptr);
861 }
862 else if(!strcmp(recvbuf, "start")) {
863 /* start is an operation that setups the trace, allocates it and starts it */
864 result = ltt_trace_setup(trace_name);
865 if(result < 0) {
866 ERR("ltt_trace_setup failed");
872037bb 867 return (void *)1;
52c51a47
PMF
868 }
869
870 result = ltt_trace_set_type(trace_name, trace_type);
871 if(result < 0) {
872 ERR("ltt_trace_set_type failed");
872037bb 873 return (void *)1;
52c51a47
PMF
874 }
875
876 result = ltt_trace_alloc(trace_name);
877 if(result < 0) {
878 ERR("ltt_trace_alloc failed");
872037bb 879 return (void *)1;
52c51a47
PMF
880 }
881
ad45e833 882 inform_consumer_daemon(trace_name);
52c51a47
PMF
883
884 result = ltt_trace_start(trace_name);
885 if(result < 0) {
886 ERR("ltt_trace_start failed");
887 continue;
888 }
d0b5f2b9
PMF
889 }
890 else if(!strcmp(recvbuf, "trace_setup")) {
891 DBG("trace setup");
fbd8191b 892
d0b5f2b9
PMF
893 result = ltt_trace_setup(trace_name);
894 if(result < 0) {
895 ERR("ltt_trace_setup failed");
872037bb 896 return (void *)1;
fbd8191b 897 }
d0b5f2b9
PMF
898
899 result = ltt_trace_set_type(trace_name, trace_type);
900 if(result < 0) {
901 ERR("ltt_trace_set_type failed");
872037bb 902 return (void *)1;
fbd8191b 903 }
d0b5f2b9
PMF
904 }
905 else if(!strcmp(recvbuf, "trace_alloc")) {
906 DBG("trace alloc");
907
908 result = ltt_trace_alloc(trace_name);
909 if(result < 0) {
910 ERR("ltt_trace_alloc failed");
872037bb 911 return (void *)1;
fbd8191b 912 }
763f41e5 913 inform_consumer_daemon(trace_name);
d0b5f2b9 914 }
62ec620f
PMF
915 else if(!strcmp(recvbuf, "trace_create")) {
916 DBG("trace create");
917
918 result = ltt_trace_setup(trace_name);
919 if(result < 0) {
920 ERR("ltt_trace_setup failed");
921 return (void *)1;
922 }
923
924 result = ltt_trace_set_type(trace_name, trace_type);
925 if(result < 0) {
926 ERR("ltt_trace_set_type failed");
927 return (void *)1;
928 }
763f41e5
DS
929 }
930 else if(!strcmp(recvbuf, "trace_start")) {
931 DBG("trace start");
62ec620f
PMF
932
933 result = ltt_trace_alloc(trace_name);
934 if(result < 0) {
935 ERR("ltt_trace_alloc failed");
936 return (void *)1;
937 }
763f41e5
DS
938 if(!result) {
939 inform_consumer_daemon(trace_name);
940 }
d0b5f2b9
PMF
941
942 result = ltt_trace_start(trace_name);
943 if(result < 0) {
944 ERR("ltt_trace_start failed");
945 continue;
fbd8191b 946 }
d0b5f2b9
PMF
947 }
948 else if(!strcmp(recvbuf, "trace_stop")) {
949 DBG("trace stop");
950
951 result = ltt_trace_stop(trace_name);
952 if(result < 0) {
953 ERR("ltt_trace_stop failed");
872037bb 954 return (void *)1;
aafb1650 955 }
d0b5f2b9
PMF
956 }
957 else if(!strcmp(recvbuf, "trace_destroy")) {
aafb1650 958
d0b5f2b9 959 DBG("trace destroy");
aafb1650 960
31d392f1 961 result = ltt_trace_destroy(trace_name, 0);
d0b5f2b9
PMF
962 if(result < 0) {
963 ERR("ltt_trace_destroy failed");
872037bb 964 return (void *)1;
fbd8191b 965 }
98963de4 966 }
b02e31e5 967 else if(nth_token_is(recvbuf, "get_shmid", 0) == 1) {
204141ee 968 do_cmd_get_shmid(recvbuf, &src);
811e4b93
PMF
969 }
970 else if(nth_token_is(recvbuf, "get_n_subbufs", 0) == 1) {
204141ee 971 do_cmd_get_n_subbufs(recvbuf, &src);
811e4b93
PMF
972 }
973 else if(nth_token_is(recvbuf, "get_subbuf_size", 0) == 1) {
204141ee 974 do_cmd_get_subbuf_size(recvbuf, &src);
3847c3ba 975 }
b02e31e5
PMF
976 else if(nth_token_is(recvbuf, "load_probe_lib", 0) == 1) {
977 char *libfile;
978
979 libfile = nth_token(recvbuf, 1);
980
981 DBG("load_probe_lib loading %s", libfile);
204141ee
PMF
982
983 free(libfile);
b02e31e5 984 }
688760ef 985 else if(nth_token_is(recvbuf, "get_subbuffer", 0) == 1) {
204141ee 986 do_cmd_get_subbuffer(recvbuf, &src);
688760ef
PMF
987 }
988 else if(nth_token_is(recvbuf, "put_subbuffer", 0) == 1) {
204141ee 989 do_cmd_put_subbuffer(recvbuf, &src);
688760ef 990 }
763f41e5
DS
991 else if(nth_token_is(recvbuf, "set_subbuf_size", 0) == 1) {
992 do_cmd_set_subbuf_size(recvbuf, &src);
993 }
994 else if(nth_token_is(recvbuf, "set_subbuf_num", 0) == 1) {
995 do_cmd_set_subbuf_num(recvbuf, &src);
996 }
52c51a47
PMF
997 else if(nth_token_is(recvbuf, "enable_marker", 0) == 1) {
998 char *channel_slash_name = nth_token(recvbuf, 1);
999 char channel_name[256]="";
1000 char marker_name[256]="";
52c51a47
PMF
1001
1002 result = sscanf(channel_slash_name, "%255[^/]/%255s", channel_name, marker_name);
1003
1004 if(channel_name == NULL || marker_name == NULL) {
1005 WARN("invalid marker name");
1006 goto next_cmd;
1007 }
52c51a47
PMF
1008
1009 result = ltt_marker_connect(channel_name, marker_name, "default");
1010 if(result < 0) {
1011 WARN("could not enable marker; channel=%s, name=%s", channel_name, marker_name);
1012 }
1013 }
1014 else if(nth_token_is(recvbuf, "disable_marker", 0) == 1) {
1015 char *channel_slash_name = nth_token(recvbuf, 1);
1016 char *marker_name;
1017 char *channel_name;
52c51a47
PMF
1018
1019 result = sscanf(channel_slash_name, "%a[^/]/%as", &channel_name, &marker_name);
1020
1021 if(marker_name == NULL) {
1022 }
52c51a47
PMF
1023
1024 result = ltt_marker_disconnect(channel_name, marker_name, "default");
1025 if(result < 0) {
1026 WARN("could not disable marker; channel=%s, name=%s", channel_name, marker_name);
1027 }
1028 }
ed1317e7
PMF
1029 else if(nth_token_is(recvbuf, "get_pidunique", 0) == 1) {
1030 char *reply;
1031
1032 asprintf(&reply, "%lld", pidunique);
1033
1034 result = ustcomm_send_reply(&ustcomm_app.server, reply, &src);
1035 if(result) {
1036 ERR("listener: get_pidunique: ustcomm_send_reply failed");
1037 goto next_cmd;
1038 }
1039
1040 free(reply);
1041 }
3a7b90de 1042// else if(nth_token_is(recvbuf, "get_notifications", 0) == 1) {
b73a4c47 1043// struct ust_trace *trace;
3a7b90de
PMF
1044// char trace_name[] = "auto";
1045// int i;
1046// char *channel_name;
1047//
1048// DBG("get_notifications");
1049//
1050// channel_name = strdup_malloc(nth_token(recvbuf, 1));
1051// if(channel_name == NULL) {
1052// ERR("put_subbuf_size: cannot parse channel");
1053// goto next_cmd;
1054// }
1055//
1056// ltt_lock_traces();
1057// trace = _ltt_trace_find(trace_name);
1058// ltt_unlock_traces();
1059//
1060// if(trace == NULL) {
63fe14e5 1061// ERR("cannot find trace!");
872037bb 1062// return (void *)1;
3a7b90de
PMF
1063// }
1064//
1065// for(i=0; i<trace->nr_channels; i++) {
1066// struct rchan *rchan = trace->channels[i].trans_channel_data;
1067// int fd;
1068//
1069// if(!strcmp(trace->channels[i].channel_name, channel_name)) {
1070// struct rchan_buf *rbuf = rchan->buf;
1071// struct ltt_channel_buf_struct *lttbuf = trace->channels[i].buf;
1072//
1073// result = fd = ustcomm_app_detach_client(&ustcomm_app, &src);
1074// if(result == -1) {
1075// ERR("ustcomm_app_detach_client failed");
1076// goto next_cmd;
1077// }
1078//
1079// lttbuf->wake_consumer_arg = (void *) fd;
1080//
1081// smp_wmb();
1082//
1083// lttbuf->call_wake_consumer = 1;
1084//
1085// break;
1086// }
1087// }
1088//
1089// free(channel_name);
1090// }
688760ef
PMF
1091 else {
1092 ERR("unable to parse message: %s", recvbuf);
1093 }
d0b5f2b9 1094
811e4b93 1095 next_cmd:
d0b5f2b9 1096 free(recvbuf);
98963de4
PMF
1097 }
1098}
1099
7958de40 1100volatile sig_atomic_t have_listener = 0;
4440ebcb 1101
98963de4
PMF
1102void create_listener(void)
1103{
9160b4e4 1104#ifdef USE_CLONE
98963de4 1105 static char listener_stack[16384];
c5fdc888 1106 int result;
4440ebcb
PMF
1107#else
1108 pthread_t thread;
9160b4e4 1109#endif
98963de4 1110
c5fdc888
PMF
1111 if(have_listener) {
1112 WARN("not creating listener because we already had one");
4440ebcb 1113 return;
c5fdc888 1114 }
4440ebcb 1115
3847c3ba 1116#ifdef USE_CLONE
c5fdc888 1117 result = clone((int (*)(void *)) listener_main, listener_stack+sizeof(listener_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL);
98963de4
PMF
1118 if(result == -1) {
1119 perror("clone");
4440ebcb 1120 return;
98963de4 1121 }
3847c3ba 1122#else
b0540e11 1123
3847c3ba
PMF
1124 pthread_create(&thread, NULL, listener_main, NULL);
1125#endif
4440ebcb
PMF
1126
1127 have_listener = 1;
98963de4
PMF
1128}
1129
98963de4 1130static int init_socket(void)
68c1021b 1131{
d0b5f2b9 1132 return ustcomm_init_app(getpid(), &ustcomm_app);
68c1021b
PMF
1133}
1134
5de74e51
PMF
1135#define AUTOPROBE_DISABLED 0
1136#define AUTOPROBE_ENABLE_ALL 1
1137#define AUTOPROBE_ENABLE_REGEX 2
1138static int autoprobe_method = AUTOPROBE_DISABLED;
1139static regex_t autoprobe_regex;
ef290fca 1140
20b37a31 1141static void auto_probe_connect(struct marker *m)
68c1021b
PMF
1142{
1143 int result;
1144
5de74e51
PMF
1145 char* concat_name = NULL;
1146 const char *probe_name = "default";
ef290fca 1147
5de74e51 1148 if(autoprobe_method == AUTOPROBE_DISABLED) {
ef290fca
PMF
1149 return;
1150 }
5de74e51
PMF
1151 else if(autoprobe_method == AUTOPROBE_ENABLE_REGEX) {
1152 result = asprintf(&concat_name, "%s/%s", m->channel, m->name);
1153 if(result == -1) {
1154 ERR("auto_probe_connect: asprintf failed (marker %s/%s)",
1155 m->channel, m->name);
1156 return;
1157 }
1158 if (regexec(&autoprobe_regex, concat_name, 0, NULL, 0)) {
1159 free(concat_name);
1160 return;
1161 }
1162 free(concat_name);
ef290fca
PMF
1163 }
1164
5de74e51 1165 result = ltt_marker_connect(m->channel, m->name, probe_name);
acbf228b
PMF
1166 if(result && result != -EEXIST)
1167 ERR("ltt_marker_connect (marker = %s/%s, errno = %d)", m->channel, m->name, -result);
20b37a31 1168
3ea1e2fc 1169 DBG("auto connected marker %s (addr: %p) %s to probe default", m->channel, m, m->name);
ef290fca 1170
20b37a31
PMF
1171}
1172
c1083aa8 1173static void __attribute__((constructor)) init()
20b37a31
PMF
1174{
1175 int result;
5de74e51 1176 char* autoprobe_val = NULL;
20b37a31 1177
ed1317e7
PMF
1178 /* Assign the pidunique, to be able to differentiate the processes with same
1179 * pid, (before and after an exec).
1180 */
1181 pidunique = make_pidunique();
1182
5de74e51 1183 DBG("Tracectl constructor");
20b37a31 1184
3847c3ba
PMF
1185 result = init_socket();
1186 if(result == -1) {
1187 ERR("init_socket error");
1188 return;
1189 }
2944a629
PMF
1190
1191 create_listener();
68c1021b 1192
5de74e51
PMF
1193 autoprobe_val = getenv("UST_AUTOPROBE");
1194 if(autoprobe_val) {
4440ebcb
PMF
1195 struct marker_iter iter;
1196
08230db7 1197 DBG("Autoprobe enabled.");
4440ebcb
PMF
1198
1199 /* Ensure markers are initialized */
1200 //init_markers();
1201
1202 /* Ensure marker control is initialized, for the probe */
1203 init_marker_control();
1204
1205 /* first, set the callback that will connect the
1206 * probe on new markers
1207 */
5de74e51
PMF
1208 if(autoprobe_val[0] == '/') {
1209 result = regcomp(&autoprobe_regex, autoprobe_val+1, 0);
1210 if (result) {
1211 char regexerr[150];
1212
1213 regerror(result, &autoprobe_regex, regexerr, sizeof(regexerr));
1214 ERR("cannot parse regex %s (%s), will ignore UST_AUTOPROBE", autoprobe_val, regexerr);
1215 /* don't crash the application just for this */
1216 }
1217 else {
1218 autoprobe_method = AUTOPROBE_ENABLE_REGEX;
1219 }
ef290fca 1220 }
5de74e51
PMF
1221 else {
1222 /* just enable all instrumentation */
1223 autoprobe_method = AUTOPROBE_ENABLE_ALL;
1224 }
1225
1226 marker_set_new_marker_cb(auto_probe_connect);
1227
4440ebcb
PMF
1228 /* Now, connect the probes that were already registered. */
1229 marker_iter_reset(&iter);
1230 marker_iter_start(&iter);
1231
08230db7 1232 DBG("now iterating on markers already registered");
4440ebcb 1233 while(iter.marker) {
08230db7 1234 DBG("now iterating on marker %s", iter.marker->name);
4440ebcb
PMF
1235 auto_probe_connect(iter.marker);
1236 marker_iter_next(&iter);
1237 }
1238 }
1239
4db647c5
PMF
1240 if(getenv("UST_TRACE")) {
1241 char trace_name[] = "auto";
1242 char trace_type[] = "ustrelay";
1243
1244 DBG("starting early tracing");
1245
1246 /* Ensure marker control is initialized */
1247 init_marker_control();
1248
4db647c5
PMF
1249 /* Ensure markers are initialized */
1250 init_markers();
1251
e17571a5
PMF
1252 /* Ensure buffers are initialized, for the transport to be available.
1253 * We are about to set a trace type and it will fail without this.
1254 */
1255 init_ustrelay_transport();
1256
027ffc9d
PMF
1257 /* FIXME: When starting early tracing (here), depending on the
1258 * order of constructors, it is very well possible some marker
1259 * sections are not yet registered. Because of this, some
1260 * channels may not be registered. Yet, we are about to ask the
1261 * daemon to collect the channels. Channels which are not yet
1262 * registered will not be collected.
1263 *
1264 * Currently, in LTTng, there is no way to add a channel after
1265 * trace start. The reason for this is that it induces complex
1266 * concurrency issues on the trace structures, which can only
1267 * be resolved using RCU. This has not been done yet. As a
1268 * workaround, we are forcing the registration of the "ust"
1269 * channel here. This is the only channel (apart from metadata)
1270 * that can be reliably used in early tracing.
1271 *
1272 * Non-early tracing does not have this problem and can use
1273 * arbitrary channel names.
1274 */
20b37a31 1275 ltt_channels_register("ust");
4db647c5
PMF
1276
1277 result = ltt_trace_setup(trace_name);
1278 if(result < 0) {
1279 ERR("ltt_trace_setup failed");
1280 return;
1281 }
1282
1283 result = ltt_trace_set_type(trace_name, trace_type);
1284 if(result < 0) {
1285 ERR("ltt_trace_set_type failed");
1286 return;
1287 }
1288
1289 result = ltt_trace_alloc(trace_name);
1290 if(result < 0) {
1291 ERR("ltt_trace_alloc failed");
1292 return;
1293 }
1294
1295 result = ltt_trace_start(trace_name);
1296 if(result < 0) {
1297 ERR("ltt_trace_start failed");
1298 return;
1299 }
60e57148
PMF
1300
1301 /* Do this after the trace is started in order to avoid creating confusion
1302 * if the trace fails to start. */
1303 inform_consumer_daemon(trace_name);
4db647c5
PMF
1304 }
1305
68c1021b
PMF
1306
1307 return;
1308
1309 /* should decrementally destroy stuff if error */
1310
1311}
1312
1313/* This is only called if we terminate normally, not with an unhandled signal,
6d45c11a
PMF
1314 * so we cannot rely on it. However, for now, LTTV requires that the header of
1315 * the last sub-buffer contain a valid end time for the trace. This is done
1316 * automatically only when the trace is properly stopped.
1317 *
1318 * If the traced program crashed, it is always possible to manually add the
1319 * right value in the header, or to open the trace in text mode.
1320 *
1321 * FIXME: Fix LTTV so it doesn't need this.
1322 */
68c1021b 1323
6d45c11a 1324static void destroy_traces(void)
68c1021b 1325{
6d45c11a 1326 int result;
a584bc4e
PMF
1327
1328 /* if trace running, finish it */
1329
6d45c11a 1330 DBG("destructor stopping traces");
a584bc4e 1331
6d45c11a
PMF
1332 result = ltt_trace_stop("auto");
1333 if(result == -1) {
1334 ERR("ltt_trace_stop error");
1335 }
1336
31d392f1 1337 result = ltt_trace_destroy("auto", 0);
6d45c11a
PMF
1338 if(result == -1) {
1339 ERR("ltt_trace_destroy error");
1340 }
68c1021b 1341}
1e2944cb 1342
97d9b88b
PMF
1343static int trace_recording(void)
1344{
1345 int retval = 0;
b73a4c47 1346 struct ust_trace *trace;
97d9b88b
PMF
1347
1348 ltt_lock_traces();
1349
1350 list_for_each_entry(trace, &ltt_traces.head, list) {
1351 if(trace->active) {
1352 retval = 1;
1353 break;
1354 }
1355 }
1356
1357 ltt_unlock_traces();
1358
1359 return retval;
1360}
1361
f293009f 1362#if 0
97d9b88b
PMF
1363static int have_consumer(void)
1364{
1365 return !list_empty(&blocked_consumers);
1366}
f293009f 1367#endif
97d9b88b 1368
f293009f 1369int restarting_usleep(useconds_t usecs)
97d9b88b
PMF
1370{
1371 struct timespec tv;
1372 int result;
1373
f293009f
PMF
1374 tv.tv_sec = 0;
1375 tv.tv_nsec = usecs * 1000;
97d9b88b
PMF
1376
1377 do {
1378 result = nanosleep(&tv, &tv);
1379 } while(result == -1 && errno == EINTR);
1380
1381 return result;
1382}
1383
f293009f
PMF
1384/* This destructor keeps the process alive for a few seconds in order
1385 * to leave time to ustd to connect to its buffers. This is necessary
1386 * for programs whose execution is very short. It is also useful in all
1387 * programs when tracing is started close to the end of the program
1388 * execution.
1389 *
1390 * FIXME: For now, this only works for the first trace created in a
1391 * process.
1392 */
1393
97d9b88b
PMF
1394static void __attribute__((destructor)) keepalive()
1395{
f293009f 1396 if(trace_recording() && buffers_to_export) {
c472cce0 1397 int total = 0;
f293009f
PMF
1398 DBG("Keeping process alive for consumer daemon...");
1399 while(buffers_to_export) {
1400 const int interv = 200000;
c472cce0 1401 restarting_usleep(interv);
f293009f
PMF
1402 total += interv;
1403
1404 if(total >= 3000000) {
c472cce0 1405 WARN("non-consumed buffers remaining after wait limit; not waiting anymore");
f293009f
PMF
1406 break;
1407 }
1408 }
1409 DBG("Finally dying...");
1410 }
6d45c11a
PMF
1411
1412 destroy_traces();
1413
2a79ceeb 1414 ustcomm_fini_app(&ustcomm_app, 0);
97d9b88b 1415}
97d9b88b 1416
775c8a3f 1417void ust_potential_exec(void)
c396a841
PMF
1418{
1419 trace_mark(ust, potential_exec, MARK_NOARGS);
1420
775c8a3f
PMF
1421 DBG("test");
1422
c396a841
PMF
1423 keepalive();
1424}
1425
1e2944cb
PMF
1426/* Notify ust that there was a fork. This needs to be called inside
1427 * the new process, anytime a process whose memory is not shared with
1428 * the parent is created. If this function is not called, the events
1429 * of the new process will not be collected.
616ed36a
PMF
1430 *
1431 * Signals should be disabled before the fork and reenabled only after
1432 * this call in order to guarantee tracing is not started before ust_fork()
1433 * sanitizes the new process.
1e2944cb
PMF
1434 */
1435
616ed36a 1436static void ust_fork(void)
1e2944cb 1437{
99b72dc0
PMF
1438 struct blocked_consumer *bc;
1439 struct blocked_consumer *deletable_bc = NULL;
1440 int result;
1441
31d392f1 1442 /* FIXME: technically, the locks could have been taken before the fork */
1e2944cb 1443 DBG("ust: forking");
73850001
PMF
1444
1445 /* break lock if necessary */
1446 ltt_unlock_traces();
1447
1e2944cb 1448 ltt_trace_stop("auto");
31d392f1 1449 ltt_trace_destroy("auto", 1);
99b72dc0
PMF
1450 /* Delete all active connections */
1451 ustcomm_close_all_connections(&ustcomm_app.server);
1452
1453 /* Delete all blocked consumers */
1454 list_for_each_entry(bc, &blocked_consumers, list) {
d9ce395d
PMF
1455 close(bc->fd_producer);
1456 close(bc->fd_consumer);
99b72dc0
PMF
1457 free(deletable_bc);
1458 deletable_bc = bc;
1459 list_del(&bc->list);
1460 }
1461
2a79ceeb
PMF
1462 /* free app, keeping socket file */
1463 ustcomm_fini_app(&ustcomm_app, 1);
393bc391 1464
cedc0155 1465 buffers_to_export = 0;
1e2944cb 1466 have_listener = 0;
99b72dc0 1467 init_socket();
9fb49d0e 1468 create_listener();
99b72dc0
PMF
1469 ltt_trace_setup("auto");
1470 result = ltt_trace_set_type("auto", "ustrelay");
1471 if(result < 0) {
1472 ERR("ltt_trace_set_type failed");
036db133 1473 return;
99b72dc0
PMF
1474 }
1475
1476 ltt_trace_alloc("auto");
1477 ltt_trace_start("auto");
ad45e833 1478 inform_consumer_daemon("auto");
1e2944cb
PMF
1479}
1480
616ed36a
PMF
1481void ust_before_fork(ust_fork_info_t *fork_info)
1482{
1483 /* Disable signals. This is to avoid that the child
1484 * intervenes before it is properly setup for tracing. It is
1485 * safer to disable all signals, because then we know we are not
1486 * breaking anything by restoring the original mask.
1487 */
1488 sigset_t all_sigs;
1489 int result;
1490
1491 /* FIXME:
1492 - only do this if tracing is active
1493 */
1494
1495 /* Disable signals */
1496 sigfillset(&all_sigs);
1497 result = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
1498 if(result == -1) {
1499 PERROR("sigprocmask");
1500 return;
1501 }
1502}
1503
1504/* Don't call this function directly in a traced program */
1505static void ust_after_fork_common(ust_fork_info_t *fork_info)
1506{
1507 int result;
616ed36a
PMF
1508
1509 /* Restore signals */
1510 result = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
1511 if(result == -1) {
1512 PERROR("sigprocmask");
1513 return;
1514 }
1515}
1516
1517void ust_after_fork_parent(ust_fork_info_t *fork_info)
1518{
1519 /* Reenable signals */
1520 ust_after_fork_common(fork_info);
1521}
1522
1523void ust_after_fork_child(ust_fork_info_t *fork_info)
1524{
1525 /* First sanitize the child */
1526 ust_fork();
1527
1528 /* Then reenable interrupts */
1529 ust_after_fork_common(fork_info);
1530}
1531
This page took 0.103016 seconds and 4 git commands to generate.