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