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