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