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