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