Remove empty line from tracepoint.h
[lttng-ust.git] / tests / ust-basic-tracing / ust-basic-tracing.c
CommitLineData
b0a99af4
MD
1/*
2 * ust-basic-tracing.c - Basic single-session, single-channel, single-process UST tracing
3 *
4 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; only version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#define _LARGEFILE64_SOURCE
22#include <errno.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <signal.h>
27#include <unistd.h>
28#include <sys/wait.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <sys/mman.h>
33#include <limits.h>
34#include <urcu/futex.h>
35#include <urcu/uatomic.h>
36#include <assert.h>
37#include <sys/socket.h>
38
39#include "lttng-ust-comm.h"
40#include "../../libringbuffer/backend.h"
41#include "../../libringbuffer/frontend.h"
42
43#define MAX_NR_STREAMS 64
44#define MAX_NR_EVENTS 128
45
46struct object_data {
47 int handle;
48 int shm_fd;
49 int wait_fd;
50 uint64_t memory_map_size;
51};
52
53static int session_handle;
54static struct object_data metadata_stream_data;
55static struct object_data metadata_data;
56static struct object_data channel_data;
57static struct object_data stream_data[MAX_NR_STREAMS];
58static int event_handle[MAX_NR_EVENTS];
8de38cf7 59static int context_handle;
b0a99af4
MD
60
61static int apps_socket = -1;
62static char apps_sock_path[PATH_MAX];
63static char local_apps_wait_shm_path[PATH_MAX];
64
65static volatile int quit_program;
66
67static void handle_signals(int signo)
68{
69 quit_program = 1;
70}
71
72static int send_app_msg(int sock, struct lttcomm_ust_msg *lum)
73{
74 ssize_t len;
75
76 len = lttcomm_send_unix_sock(sock, lum, sizeof(*lum));
77 switch (len) {
78 case sizeof(*lum):
79 printf("message successfully sent\n");
80 break;
81 case -1:
82 if (errno == ECONNRESET) {
83 printf("remote end closed connection\n");
84 return 0;
85 }
86 return -1;
87 default:
88 printf("incorrect message size: %zd\n", len);
89 return -1;
90 }
91 return 0;
92}
93
94static int recv_app_reply(int sock, struct lttcomm_ust_reply *lur,
95 uint32_t expected_handle, uint32_t expected_cmd)
96{
97 ssize_t len;
98
99 memset(lur, 0, sizeof(*lur));
100 len = lttcomm_recv_unix_sock(sock, lur, sizeof(*lur));
101 switch (len) {
102 case 0: /* orderly shutdown */
103 printf("Application has performed an orderly shutdown\n");
104 return -EINVAL;
105 case sizeof(*lur):
106 printf("result message received\n");
107 if (lur->handle != expected_handle) {
108 printf("Unexpected result message handle\n");
109 return -EINVAL;
110 }
111
112 if (lur->cmd != expected_cmd) {
113 printf("Unexpected result message command\n");
114 return -EINVAL;
115 }
116 if (lur->ret_code != LTTCOMM_OK) {
117 printf("remote operation failed with code %d.\n",
118 lur->ret_code);
119 return lur->ret_code;
120 }
121 return 0;
122 case -1:
123 if (errno == ECONNRESET) {
124 printf("remote end closed connection\n");
125 return -EINVAL;
126 }
127 return -1;
128 default:
129 printf("incorrect message size: %zd\n", len);
130 return len > 0 ? -1 : len;
131 }
132}
133
134static int send_app_cmd(int sock,
135 struct lttcomm_ust_msg *lum,
136 struct lttcomm_ust_reply *lur)
137{
138 int ret;
139
140 ret = send_app_msg(sock, lum);
141 if (ret)
142 return ret;
143 ret = recv_app_reply(sock, lur, lum->handle, lum->cmd);
144 if (ret)
145 return ret;
146 return 0;
147}
148
149
150/*
151 * Receives a single fd from socket.
152 *
153 * Returns the size of received data
154 */
155static int lttcomm_recv_fd(int sock)
156{
157 struct iovec iov[1];
158 int ret = 0;
159 int data_fd;
160 struct cmsghdr *cmsg;
161 char recv_fd[CMSG_SPACE(sizeof(int))];
162 struct msghdr msg = { 0 };
af327df1
MD
163 union {
164 unsigned char vc[4];
165 int vi;
166 } tmp;
167 int i;
b0a99af4
MD
168
169 /* Prepare to receive the structures */
170 iov[0].iov_base = &data_fd;
171 iov[0].iov_len = sizeof(data_fd);
172 msg.msg_iov = iov;
173 msg.msg_iovlen = 1;
174 msg.msg_control = recv_fd;
175 msg.msg_controllen = sizeof(recv_fd);
176
177 printf("Waiting to receive fd\n");
178 if ((ret = recvmsg(sock, &msg, 0)) < 0) {
179 perror("recvmsg");
180 goto end;
181 }
182 if (ret != sizeof(data_fd)) {
183 printf("Received %d bytes, expected %ld", ret, sizeof(data_fd));
184 goto end;
185 }
186 cmsg = CMSG_FIRSTHDR(&msg);
187 if (!cmsg) {
188 printf("Invalid control message header\n");
189 ret = -1;
190 goto end;
191 }
192 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
193 printf("Didn't received any fd\n");
194 ret = -1;
195 goto end;
196 }
197 /* this is our fd */
af327df1 198 for (i = 0; i < sizeof(int); i++)
aca7316c 199 tmp.vc[i] = CMSG_DATA(cmsg)[i];
af327df1 200 ret = tmp.vi;
b0a99af4
MD
201 printf("received fd %d\n", ret);
202end:
203 return ret;
204}
205
206
207static
208int open_streams(int sock, int channel_handle, struct object_data *stream_datas,
209 int nr_check)
210{
211 int ret, k = 0;
212
213 for (;;) {
214 struct lttcomm_ust_msg lum;
215 struct lttcomm_ust_reply lur;
216
217 memset(&lum, 0, sizeof(lum));
218 lum.handle = channel_handle;
219 lum.cmd = LTTNG_UST_STREAM;
220 ret = send_app_cmd(sock, &lum, &lur);
221 if (!ret) {
222 assert(k < nr_check);
223 stream_datas[k].handle = lur.ret_val;
224 printf("received stream handle %u\n",
225 stream_datas[k].handle);
226 if (lur.ret_code == LTTCOMM_OK) {
227 ssize_t len;
228
229 stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
230 /* get shm fd */
231 len = lttcomm_recv_fd(sock);
232 if (len < 0)
233 return -EINVAL;
234 stream_datas[k].shm_fd = len;
235 /* get wait fd */
236 len = lttcomm_recv_fd(sock);
237 if (len < 0)
238 return -EINVAL;
239 stream_datas[k].wait_fd = len;
240 }
241 k++;
242 }
243 if (ret == -ENOENT)
244 break;
245 if (ret)
246 return ret;
247 }
248 return 0;
249}
250
251static
252int close_streams(int sock, struct object_data *stream_datas, int nr_check)
253{
254 int ret, k;
255
256 for (k = 0; k < nr_check; k++) {
257 struct lttcomm_ust_msg lum;
258 struct lttcomm_ust_reply lur;
259
260 if (!stream_datas[k].handle)
261 continue;
262 memset(&lum, 0, sizeof(lum));
263 lum.handle = stream_datas[k].handle;
264 lum.cmd = LTTNG_UST_RELEASE;
265 ret = send_app_cmd(sock, &lum, &lur);
266 if (ret) {
267 printf("Error closing stream\n");
268 return ret;
269 }
270 if (stream_datas[k].shm_fd >= 0) {
271 ret = close(stream_datas[k].shm_fd);
272 if (ret) {
273 printf("Error closing stream shm_fd\n");
274 return ret;
275 }
276 }
277 if (stream_datas[k].wait_fd >= 0) {
278 ret = close(stream_datas[k].wait_fd);
279 if (ret) {
280 printf("Error closing stream wait_fd\n");
281 return ret;
282 }
283 }
284 }
285 return 0;
286}
287
288static
289struct shm_handle *map_channel(struct object_data *chan_data,
290 struct object_data *stream_datas, int nr_check)
291{
292 struct shm_handle *handle;
293 struct channel *chan;
294 int k, ret;
295
296 /* map metadata channel */
297 handle = channel_handle_create(chan_data->shm_fd,
298 chan_data->wait_fd,
299 chan_data->memory_map_size);
300 if (!handle) {
301 printf("create handle error\n");
302 return NULL;
303 }
304 chan_data->shm_fd = -1;
305 chan_data->wait_fd = -1;
306 chan = shmp(handle, handle->chan);
307
308 for (k = 0; k < nr_check; k++) {
309 struct object_data *stream_data = &stream_datas[k];
310
311 if (!stream_data->handle)
312 break;
313 /* map stream */
314 ret = channel_handle_add_stream(handle,
315 stream_data->shm_fd,
316 stream_data->wait_fd,
317 stream_data->memory_map_size);
318 if (ret) {
319 printf("add stream error\n");
320 goto error_destroy;
321 }
322 stream_data->shm_fd = -1;
323 stream_data->wait_fd = -1;
324 }
325 return handle;
326
327error_destroy:
328 channel_destroy(chan, handle, 1);
329 return NULL;
330}
331
332static
333void unmap_channel(struct shm_handle *handle)
334{
335 struct channel *chan;
336
337 chan = shmp(handle, handle->chan);
338 /* unmap channel */
339 channel_destroy(chan, handle, 1);
340}
341
342static
343int consume_stream(struct shm_handle *handle, int cpu, char *outfile)
344{
345 struct channel *chan;
346 struct lib_ring_buffer *buf;
347 int outfd, ret;
348 int shm_fd, wait_fd;
349 uint64_t memory_map_size;
350
351 chan = shmp(handle, handle->chan);
352
353 /* open stream */
354 buf = channel_get_ring_buffer(&chan->backend.config,
355 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
356 if (!buf)
357 return -ENOENT;
358 ret = lib_ring_buffer_open_read(buf, handle, 1);
359 if (ret) {
360 return -1;
361 }
362
363 /* copy */
364 outfd = open(outfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC,
365 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
366 if (outfd < 0) {
367 perror("open output");
368 return -1;
369 }
370
371 printf("Waiting for buffer data for %s\n", outfile);
372 for (;;) {
373 unsigned long read_size;
374 unsigned long copy_size;
375 char *ptr;
376
377 ret = lib_ring_buffer_get_next_subbuf(buf, handle);
378 printf("get next ret %d\n", ret);
379 if (ret == -ENODATA)
380 break;
381 if (ret == -EAGAIN) {
382 sleep(1);
383 continue;
384 }
385 if (ret) {
386 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret);
387 return -1;
388 }
389 read_size = lib_ring_buffer_get_read_data_size(
390 &chan->backend.config, buf, handle);
391 read_size = PAGE_ALIGN(read_size);
392 ptr = lib_ring_buffer_read_offset_address(
393 &buf->backend, 0, handle);
394 printf("WRITE: copy %lu bytes\n", read_size);
395 copy_size = write(outfd, ptr, read_size);
396 if (copy_size < read_size) {
397 printf("write issue: copied %zd, expected %lu\n", copy_size, read_size);
398 }
399 lib_ring_buffer_put_next_subbuf(buf, handle);
400 }
401
402 ret = close(outfd);
403 if (ret) {
404 perror("close");
405 return -1;
406 }
407
408 /* close stream */
409 lib_ring_buffer_release_read(buf, handle, 1);
410 return 0;
411}
412
413static
414int consume_buffers(const char *outputpath)
415{
416 int k, ret;
417 mode_t old_umask;
418 char pathname[PATH_MAX];
419 struct shm_handle *handle;
420
421 snprintf(pathname, PATH_MAX - 1, "%s", outputpath);
422 old_umask = umask(0);
423 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
424 if (ret && errno != EEXIST) {
425 perror("mkdir");
426 umask(old_umask);
427 return -1;
428 }
429 umask(old_umask);
430
431 /* copy metadata */
432 handle = map_channel(&metadata_data,
433 &metadata_stream_data, 1);
434 if (!handle)
435 return -1;
436 snprintf(pathname, PATH_MAX - 1,
437 "%s/metadata", outputpath);
438 ret = consume_stream(handle, -1, pathname);
439 if (ret && ret != -ENOENT) {
440 printf("Error in consume_stream\n");
441 return ret;
442 }
443 unmap_channel(handle);
444
445 /* copy binary data */
446 handle = map_channel(&channel_data,
447 stream_data, MAX_NR_STREAMS);
448 if (!handle)
449 return -1;
450 for (k = 0; k < MAX_NR_STREAMS; k++) {
451 snprintf(pathname, PATH_MAX - 1,
452 "%s/data_%u", outputpath, k);
453 ret = consume_stream(handle, k, pathname);
454 if (ret && ret != -ENOENT) {
455 printf("Error in consume_stream\n");
456 return ret;
457 }
458 }
459 unmap_channel(handle);
460
461 return 0;
462}
463
464int send_app_msgs(int sock, const char *outputpath,
465 unsigned int nr_events, const char **event_names)
466{
467 struct lttcomm_ust_msg lum;
468 struct lttcomm_ust_reply lur;
469 int ret, k;
470
471 /* Create session */
472 memset(&lum, 0, sizeof(lum));
473 lum.handle = LTTNG_UST_ROOT_HANDLE;
474 lum.cmd = LTTNG_UST_SESSION;
475 ret = send_app_cmd(sock, &lum, &lur);
476 if (ret)
477 return ret;
478 session_handle = lur.ret_val;
479 printf("received session handle %u\n", session_handle);
480
481 /* Create metadata channel */
482 memset(&lum, 0, sizeof(lum));
483 lum.handle = session_handle;
484 lum.cmd = LTTNG_UST_METADATA;
485 lum.u.channel.overwrite = 0;
486 lum.u.channel.subbuf_size = 32768;
487 lum.u.channel.num_subbuf = 4;
488 lum.u.channel.switch_timer_interval = 0;
489 lum.u.channel.read_timer_interval = 0;
490 lum.u.channel.output = LTTNG_UST_MMAP;
491 ret = send_app_cmd(sock, &lum, &lur);
492 if (ret)
493 return ret;
494 metadata_data.handle = lur.ret_val;
495 printf("received metadata handle %u\n", metadata_data.handle);
496 if (lur.ret_code == LTTCOMM_OK) {
497 ssize_t len;
498
499 metadata_data.memory_map_size = lur.u.channel.memory_map_size;
500 /* get shm fd */
501 len = lttcomm_recv_fd(sock);
502 if (len < 0)
503 return -EINVAL;
504 metadata_data.shm_fd = len;
505 /* get wait fd */
506 len = lttcomm_recv_fd(sock);
507 if (len < 0)
508 return -EINVAL;
509 metadata_data.wait_fd = len;
510 }
511
512 ret = open_streams(sock, metadata_data.handle,
513 &metadata_stream_data, 1);
514 if (ret) {
515 printf("Error in open_streams\n");
516 return ret;
517 }
518
519 /* Create data channel */
520 memset(&lum, 0, sizeof(lum));
521 lum.handle = session_handle;
522 lum.cmd = LTTNG_UST_CHANNEL;
523 //lum.u.channel.overwrite = 0;
524 lum.u.channel.overwrite = 1;
525 lum.u.channel.subbuf_size = 32768;
526 lum.u.channel.num_subbuf = 8;
527 //lum.u.channel.num_subbuf = 4;
528 //lum.u.channel.num_subbuf = 2;
529 lum.u.channel.switch_timer_interval = 0;
530 lum.u.channel.read_timer_interval = 0;
531 lum.u.channel.output = LTTNG_UST_MMAP;
532 ret = send_app_cmd(sock, &lum, &lur);
533 if (ret)
534 return ret;
535 channel_data.handle = lur.ret_val;
536 printf("received channel handle %u\n", channel_data.handle);
537 if (lur.ret_code == LTTCOMM_OK) {
538 ssize_t len;
539
540 channel_data.memory_map_size = lur.u.channel.memory_map_size;
541 /* get shm fd */
542 len = lttcomm_recv_fd(sock);
543 if (len < 0)
544 return -EINVAL;
545 channel_data.shm_fd = len;
546 /* get wait fd */
547 len = lttcomm_recv_fd(sock);
548 if (len < 0)
549 return -EINVAL;
550 channel_data.wait_fd = len;
551 }
552
553 /* Create events */
554 for (k = 0; k < nr_events; k++) {
555 memset(&lum, 0, sizeof(lum));
556 lum.handle = channel_data.handle;
557 lum.cmd = LTTNG_UST_EVENT;
558 strncpy(lum.u.event.name, event_names[k],
559 LTTNG_UST_SYM_NAME_LEN);
560 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
561 ret = send_app_cmd(sock, &lum, &lur);
562 if (ret)
563 return ret;
564 event_handle[k] = lur.ret_val;
565 printf("received event handle %u\n", event_handle[k]);
566 }
567
3b402b40 568 /* Attach vtid context */
8de38cf7
MD
569 memset(&lum, 0, sizeof(lum));
570 lum.handle = channel_data.handle;
571 lum.cmd = LTTNG_UST_CONTEXT;
3b402b40
MD
572 lum.u.context.ctx = LTTNG_UST_CONTEXT_VTID;
573 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PTHREAD_ID;
4847e9bb
MD
574 //lum.u.context.ctx = LTTNG_UST_CONTEXT_VPID;
575 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PROCNAME;
8de38cf7
MD
576 ret = send_app_cmd(sock, &lum, &lur);
577 if (ret)
578 return ret;
579 context_handle = lur.ret_val;
580 printf("received context handle %u\n", context_handle);
581
b0a99af4
MD
582 /* Get references to channel streams */
583 ret = open_streams(sock, channel_data.handle,
584 stream_data, MAX_NR_STREAMS);
585 if (ret) {
586 printf("Error in open_streams\n");
587 return ret;
588 }
589
590 memset(&lum, 0, sizeof(lum));
591 lum.handle = session_handle;
592 lum.cmd = LTTNG_UST_SESSION_START;
593 ret = send_app_cmd(sock, &lum, &lur);
594 if (ret)
595 return ret;
596 printf("Session handle %u started.\n", session_handle);
597
598 /* Tell application registration is done */
599 memset(&lum, 0, sizeof(lum));
600 lum.handle = LTTNG_UST_ROOT_HANDLE;
601 lum.cmd = LTTNG_UST_REGISTER_DONE;
602 ret = send_app_cmd(sock, &lum, &lur);
603 if (ret)
604 return ret;
605 printf("Registration done acknowledged.\n");
606
607 sleep(4);
608
609 ret = consume_buffers(outputpath);
610 if (ret) {
611 printf("Error in consume_buffers\n");
612 return ret;
613 }
614
615 /* Release data channel */
616 /* Release streams */
617 ret = close_streams(sock, stream_data,
618 MAX_NR_STREAMS);
619 if (ret)
620 return ret;
621
8de38cf7
MD
622 /* Release context */
623 memset(&lum, 0, sizeof(lum));
624 lum.handle = context_handle;
625 lum.cmd = LTTNG_UST_RELEASE;
626 ret = send_app_cmd(sock, &lum, &lur);
627 if (ret)
628 return ret;
629
b0a99af4
MD
630 /* Release events */
631 for (k = 0; k < nr_events; k++) {
632 memset(&lum, 0, sizeof(lum));
633 lum.handle = event_handle[k];
634 lum.cmd = LTTNG_UST_RELEASE;
635 ret = send_app_cmd(sock, &lum, &lur);
636 if (ret)
637 return ret;
638 }
639 memset(&lum, 0, sizeof(lum));
640 lum.handle = channel_data.handle;
641 lum.cmd = LTTNG_UST_RELEASE;
642 ret = send_app_cmd(sock, &lum, &lur);
643 if (ret)
644 return ret;
645 if (channel_data.shm_fd >= 0) {
646 ret = close(channel_data.shm_fd);
647 if (ret)
648 return ret;
649 }
650 if (channel_data.wait_fd >= 0) {
651 ret = close(channel_data.wait_fd);
652 if (ret)
653 return ret;
654 }
655
656 /* Release metadata channel */
657 ret = close_streams(sock, &metadata_stream_data, 1);
658 if (ret)
659 return ret;
660
661 memset(&lum, 0, sizeof(lum));
662 lum.handle = metadata_data.handle;
663 lum.cmd = LTTNG_UST_RELEASE;
664 ret = send_app_cmd(sock, &lum, &lur);
665 if (ret)
666 return ret;
667 if (metadata_data.shm_fd >= 0) {
668 ret = close(metadata_data.shm_fd);
669 if (ret)
670 return ret;
671 }
672 if (metadata_data.wait_fd >= 0) {
673 ret = close(metadata_data.wait_fd);
674 if (ret)
675 return ret;
676 }
677
678 /* Release session */
679 memset(&lum, 0, sizeof(lum));
680 lum.handle = session_handle;
681 lum.cmd = LTTNG_UST_RELEASE;
682 ret = send_app_cmd(sock, &lum, &lur);
683 if (ret)
684 return ret;
685
686 return 0;
687}
688
689/*
690 * Using fork to set umask in the child process (not multi-thread safe). We
691 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
692 * the shm and does not let everybody modify it, to ensure safety against
693 * shm_unlink) by simply letting the mmap fail and retrying after a few
694 * seconds. For global shm, everybody has rw access to it until the sessiond
695 * starts.
696 */
697static int get_wait_shm(char *shm_path, size_t mmap_size, int global)
698{
699 int wait_shm_fd, ret;
700 mode_t mode;
701
702 /* Default permissions */
703 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
704
705 /* Change owner of the shm path */
706 if (global) {
707 ret = chown(shm_path, 0, 0);
708 if (ret < 0) {
709 if (errno != ENOENT) {
710 perror("chown wait shm");
711 goto error;
712 }
713 }
714
715 /*
716 * If global session daemon, any application can register so the shm
717 * needs to be set in read-only mode for others.
718 */
719 mode |= S_IROTH;
720 } else {
721 ret = chown(shm_path, getuid(), getgid());
722 if (ret < 0) {
723 if (errno != ENOENT) {
724 perror("chown wait shm");
725 goto error;
726 }
727 }
728 }
729
730 /*
731 * Set permissions to the shm even if we did not create the shm.
732 */
733 ret = chmod(shm_path, mode);
734 if (ret < 0) {
735 if (errno != ENOENT) {
736 perror("chmod wait shm");
737 goto error;
738 }
739 }
740
741 /*
742 * We're alone in a child process, so we can modify the process-wide
743 * umask.
744 */
745 umask(~mode);
746
747 /*
748 * Try creating shm (or get rw access). We don't do an exclusive open,
749 * because we allow other processes to create+ftruncate it concurrently.
750 */
751 wait_shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, mode);
752 if (wait_shm_fd < 0) {
753 perror("shm_open wait shm");
754 goto error;
755 }
756
757 ret = ftruncate(wait_shm_fd, mmap_size);
758 if (ret < 0) {
759 perror("ftruncate wait shm");
760 exit(EXIT_FAILURE);
761 }
762
763 ret = fchmod(wait_shm_fd, mode);
764 if (ret < 0) {
765 perror("fchmod");
766 exit(EXIT_FAILURE);
767 }
768
769 printf("Got the wait shm fd %d\n", wait_shm_fd);
770
771 return wait_shm_fd;
772
773error:
774 printf("Failing to get the wait shm fd\n");
775
776 return -1;
777}
778
779int update_futex(int fd, int active)
780{
781 size_t mmap_size = sysconf(_SC_PAGE_SIZE);
782 char *wait_shm_mmap;
783 int ret;
784
785 wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
786 MAP_SHARED, fd, 0);
787 if (wait_shm_mmap == MAP_FAILED) {
788 perror("mmap");
789 goto error;
790 }
791
792 if (active) {
793 uatomic_set((int32_t *) wait_shm_mmap, 1);
794 futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
795 INT_MAX, NULL, NULL, 0);
796 } else {
797 uatomic_set((int32_t *) wait_shm_mmap, 0);
798 }
799 ret = munmap(wait_shm_mmap, mmap_size);
800 if (ret) {
801 perror("Error unmapping wait shm");
802 goto error;
803 }
804 return 0;
805error:
806 return -1;
807}
808
809/*
810 * Set open files limit to unlimited. This daemon can open a large number of
811 * file descriptors in order to consumer multiple kernel traces.
812 */
813static void set_ulimit(void)
814{
815 int ret;
816 struct rlimit lim;
817
818 /*
819 * If not root, we cannot increase our max open files. But our
820 * scope is then limited to processes from a single user.
821 */
822 if (getuid() != 0)
823 return;
824 /* The kernel does not allowed an infinite limit for open files */
825 lim.rlim_cur = 65535;
826 lim.rlim_max = 65535;
827
828 ret = setrlimit(RLIMIT_NOFILE, &lim);
829 if (ret < 0) {
830 perror("failed to set open files limit");
831 }
832}
833
834/*
835 * Usage:
836 * ./ust-basic-tracing outputpath event_name1 event_name2 ....
837 */
838int main(int argc, const char **argv)
839{
840 const char *home_dir;
841 int ret, wait_shm_fd;
842 struct sigaction act;
fb50c39d 843 mode_t old_umask = 0;
b0a99af4
MD
844 const char *outputpath;
845 const char **event_names;
846 unsigned int nr_events;
847
848 if (argc < 2) {
849 printf("Usage:\n");
850 printf("%s outputpath event_name1 event_name2 ...\n",
851 argv[0]);
852 exit(-1);
853 }
854 outputpath = argv[1];
855 event_names = &argv[2];
856 nr_events = argc - 2;
857
858 set_ulimit();
859
860 /* Ignore sigpipe */
861 memset(&act, 0, sizeof(act));
862 ret = sigemptyset(&act.sa_mask);
863 if (ret == -1) {
864 perror("sigemptyset");
865 return -1;
866 }
867
868 act.sa_handler = SIG_IGN;
869 ret = sigaction(SIGPIPE, &act, NULL);
870 if (ret == -1) {
871 perror("sigaction");
872 return -1;
873 }
874
875 /* Handle SIGTERM */
876 act.sa_handler = handle_signals;
877 ret = sigaction(SIGTERM, &act, NULL);
878 if (ret == -1) {
879 perror("sigaction");
880 return -1;
881 }
882 /* Handle SIGINT */
883 ret = sigaction(SIGINT, &act, NULL);
884 if (ret == -1) {
885 perror("sigaction");
886 return -1;
887 }
888
889 if (geteuid() == 0) {
890 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
891 if (ret && errno != EEXIST) {
892 perror("mkdir");
893 return -1;
894 }
895 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
896 sysconf(_SC_PAGE_SIZE), 1);
897 if (wait_shm_fd < 0) {
898 perror("global wait shm error");
899 return -1;
900 }
901 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
902 old_umask = umask(0);
903 } else {
904 snprintf(local_apps_wait_shm_path, PATH_MAX,
905 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
906 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
907 sysconf(_SC_PAGE_SIZE), 0);
908 if (wait_shm_fd < 0) {
909 perror("local wait shm error");
910 return -1;
911 }
912 home_dir = (const char *) getenv("HOME");
913 if (!home_dir) {
914 perror("getenv error");
915 return -ENOENT;
916 }
917 snprintf(apps_sock_path, PATH_MAX,
918 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
919 }
920
921 ret = lttcomm_create_unix_sock(apps_sock_path);
922 if (ret < 0) {
923 perror("create error");
924 return ret;
925 }
926 apps_socket = ret;
927
928 if (getuid() == 0) {
929 /* File permission MUST be 666 */
930 ret = chmod(apps_sock_path,
931 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
932 if (ret < 0) {
933 printf("Set file permissions failed: %s\n", apps_sock_path);
934 perror("chmod");
935 goto end;
936 }
937 umask(old_umask);
938 }
939 ret = lttcomm_listen_unix_sock(apps_socket);
940 if (ret < 0) {
941 perror("listen error");
942 return ret;
943 }
944
945 /* wake up futexes */
946 ret = update_futex(wait_shm_fd, 1);
947 if (ret) {
948 fprintf(stderr, "Error wakeup futex\n");
949 return -1;
950 }
951
952 for (;;) {
953 int sock;
954 ssize_t len;
955 struct {
956 uint32_t major;
957 uint32_t minor;
958 pid_t pid;
959 pid_t ppid;
960 uid_t uid;
961 gid_t gid;
962 char name[16]; /* Process name */
963 } reg_msg;
964 char bufname[17];
965
966 if (quit_program)
967 break;
968
969 printf("Accepting application registration\n");
970 sock = lttcomm_accept_unix_sock(apps_socket);
971 if (sock < 0) {
972 perror("accept error");
973 goto end;
974 }
975
976 /*
977 * Basic recv here to handle the very simple data
978 * that the libust send to register (reg_msg).
979 */
980 len = lttcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
981 if (len < 0 || len != sizeof(reg_msg)) {
982 perror("lttcomm_recv_unix_sock");
983 continue;
984 }
985 memcpy(bufname, reg_msg.name, 16);
986 bufname[16] = '\0';
987 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
988 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
989 reg_msg.gid, reg_msg.major, reg_msg.minor);
990 ret = send_app_msgs(sock, outputpath, nr_events, event_names);
991 if (ret) {
992 printf("Error in send_app_msgs.\n");
993 sleep(1);
994 }
995 close(sock);
996 }
997
998end:
999 printf("quitting.\n");
1000 /* Let applications know we are not responding anymore */
1001 ret = update_futex(wait_shm_fd, 0);
1002 if (ret) {
1003 fprintf(stderr, "Error wakeup futex\n");
1004 return -1;
1005 }
1006
1007 return 0;
1008}
This page took 0.060789 seconds and 4 git commands to generate.