Cleanup warnings
[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 };
170
171 /* Prepare to receive the structures */
172 iov[0].iov_base = &data_fd;
173 iov[0].iov_len = sizeof(data_fd);
174 msg.msg_iov = iov;
175 msg.msg_iovlen = 1;
176 msg.msg_control = recv_fd;
177 msg.msg_controllen = sizeof(recv_fd);
178
179 printf("Waiting to receive fd\n");
180 if ((ret = recvmsg(sock, &msg, 0)) < 0) {
181 perror("recvmsg");
182 goto end;
183 }
184 if (ret != sizeof(data_fd)) {
185 printf("Received %d bytes, expected %ld", ret, sizeof(data_fd));
186 goto end;
187 }
188 cmsg = CMSG_FIRSTHDR(&msg);
189 if (!cmsg) {
190 printf("Invalid control message header\n");
191 ret = -1;
192 goto end;
193 }
194 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
195 printf("Didn't received any fd\n");
196 ret = -1;
197 goto end;
198 }
199 /* this is our fd */
200 ret = ((int *) CMSG_DATA(cmsg))[0];
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(void)
415{
416 int i, j, k, ret;
417 mode_t old_umask;
418
419 for (i = 0; i < NR_SESSIONS; i++) {
420 char pathname[PATH_MAX];
421 struct shm_handle *handle;
422
423 snprintf(pathname, PATH_MAX - 1, "/tmp/testtrace%u", i);
424 old_umask = umask(0);
425 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
426 if (ret && errno != EEXIST) {
427 perror("mkdir");
428 umask(old_umask);
429 return -1;
430 }
431 umask(old_umask);
432
433 /* copy metadata */
434 handle = map_channel(&metadata_data[i],
435 &metadata_stream_data[i], 1);
436 if (!handle)
437 return -1;
438 snprintf(pathname, PATH_MAX - 1,
439 "/tmp/testtrace%u/metadata", i);
440 ret = consume_stream(handle, -1, pathname);
441 if (ret && ret != -ENOENT) {
442 printf("Error in consume_stream\n");
443 return ret;
444 }
445 unmap_channel(handle);
446
447 /* copy binary data */
448 for (j = 0; j < NR_CHANNELS; j++) {
449 handle = map_channel(&channel_data[i][j],
450 stream_data[i][j], MAX_NR_STREAMS);
451 if (!handle)
452 return -1;
453 for (k = 0; k < MAX_NR_STREAMS; k++) {
454 snprintf(pathname, PATH_MAX - 1,
455 "/tmp/testtrace%u/data_%u", i, k);
456 ret = consume_stream(handle, k, pathname);
457 if (ret && ret != -ENOENT) {
458 printf("Error in consume_stream\n");
459 return ret;
460 }
461 }
462 unmap_channel(handle);
463 }
464 }
465
466 return 0;
467}
468
469int send_app_msgs(int sock)
470{
471 struct lttcomm_ust_msg lum;
472 struct lttcomm_ust_reply lur;
473 int ret, i, j, k;
474
475 for (i = 0; i < NR_SESSIONS; i++) {
476 /* Create session */
477 memset(&lum, 0, sizeof(lum));
478 lum.handle = LTTNG_UST_ROOT_HANDLE;
479 lum.cmd = LTTNG_UST_SESSION;
480 ret = send_app_cmd(sock, &lum, &lur);
481 if (ret)
482 return ret;
483 session_handle[i] = lur.ret_val;
484 printf("received session handle %u\n", session_handle[i]);
485
486 /* Create metadata channel */
487 memset(&lum, 0, sizeof(lum));
488 lum.handle = session_handle[i];
489 lum.cmd = LTTNG_UST_METADATA;
490 lum.u.channel.overwrite = 0;
491 lum.u.channel.subbuf_size = 32768;
492 lum.u.channel.num_subbuf = 4;
493 lum.u.channel.switch_timer_interval = 0;
494 lum.u.channel.read_timer_interval = 0;
495 lum.u.channel.output = LTTNG_UST_MMAP;
496 ret = send_app_cmd(sock, &lum, &lur);
497 if (ret)
498 return ret;
499 metadata_data[i].handle = lur.ret_val;
500 printf("received metadata handle %u\n", metadata_data[i].handle);
501 if (lur.ret_code == LTTCOMM_OK) {
502 ssize_t len;
503
504 metadata_data[i].memory_map_size = lur.u.channel.memory_map_size;
505 /* get shm fd */
506 len = lttcomm_recv_fd(sock);
507 if (len < 0)
508 return -EINVAL;
509 metadata_data[i].shm_fd = len;
510 /* get wait fd */
511 len = lttcomm_recv_fd(sock);
512 if (len < 0)
513 return -EINVAL;
514 metadata_data[i].wait_fd = len;
515 }
516
517 ret = open_streams(sock, metadata_data[i].handle,
518 &metadata_stream_data[i], 1);
519 if (ret) {
520 printf("Error in open_streams\n");
521 return ret;
522 }
523
524 /* Create channels */
525 for (j = 0; j < NR_CHANNELS; j++) {
526 memset(&lum, 0, sizeof(lum));
527 lum.handle = session_handle[i];
528 lum.cmd = LTTNG_UST_CHANNEL;
529 //lum.u.channel.overwrite = 0;
530 lum.u.channel.overwrite = 1;
531 lum.u.channel.subbuf_size = 32768;
532 lum.u.channel.num_subbuf = 8;
533 //lum.u.channel.num_subbuf = 4;
534 //lum.u.channel.num_subbuf = 2;
535 lum.u.channel.switch_timer_interval = 0;
536 lum.u.channel.read_timer_interval = 0;
537 lum.u.channel.output = LTTNG_UST_MMAP;
538 ret = send_app_cmd(sock, &lum, &lur);
539 if (ret)
540 return ret;
541 channel_data[i][j].handle = lur.ret_val;
542 printf("received channel handle %u\n", channel_data[i][j].handle);
543 if (lur.ret_code == LTTCOMM_OK) {
544 ssize_t len;
545
546 channel_data[i][j].memory_map_size = lur.u.channel.memory_map_size;
547 /* get shm fd */
548 len = lttcomm_recv_fd(sock);
549 if (len < 0)
550 return -EINVAL;
551 channel_data[i][j].shm_fd = len;
552 /* get wait fd */
553 len = lttcomm_recv_fd(sock);
554 if (len < 0)
555 return -EINVAL;
556 channel_data[i][j].wait_fd = len;
557 }
558
559 /* Create events */
560 for (k = 0; k < NR_EVENTS; k++) {
561 memset(&lum, 0, sizeof(lum));
562 lum.handle = channel_data[i][j].handle;
563 lum.cmd = LTTNG_UST_EVENT;
564 strncpy(lum.u.event.name, evname[k],
565 LTTNG_UST_SYM_NAME_LEN);
566 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
567 ret = send_app_cmd(sock, &lum, &lur);
568 if (ret)
569 return ret;
570 event_handle[i][j][k] = lur.ret_val;
571 printf("received event handle %u\n", event_handle[i][j][k]);
572 }
573
574 /* Get references to channel streams */
575 ret = open_streams(sock, channel_data[i][j].handle,
576 stream_data[i][j], MAX_NR_STREAMS);
577 if (ret) {
578 printf("Error in open_streams\n");
579 return ret;
580 }
581 }
582
583 memset(&lum, 0, sizeof(lum));
584 lum.handle = session_handle[i];
585 lum.cmd = LTTNG_UST_SESSION_START;
586 ret = send_app_cmd(sock, &lum, &lur);
587 if (ret)
588 return ret;
589 printf("Session handle %u started.\n", session_handle[i]);
590 }
591
592 /* Tell application registration is done */
593 memset(&lum, 0, sizeof(lum));
594 lum.handle = LTTNG_UST_ROOT_HANDLE;
595 lum.cmd = LTTNG_UST_REGISTER_DONE;
596 ret = send_app_cmd(sock, &lum, &lur);
597 if (ret)
598 return ret;
599 printf("Registration done acknowledged.\n");
600
601 sleep(4);
602
603 ret = consume_buffers();
604 if (ret) {
605 printf("Error in consume_buffers\n");
606 return ret;
607 }
608
609 for (i = 0; i < NR_SESSIONS; i++) {
610 /* Release channels */
611 for (j = 0; j < NR_CHANNELS; j++) {
612 /* Release streams */
613 ret = close_streams(sock, stream_data[i][j],
614 MAX_NR_STREAMS);
615 if (ret)
616 return ret;
617
618 /* Release events */
619 for (k = 0; k < NR_EVENTS; k++) {
620 memset(&lum, 0, sizeof(lum));
621 lum.handle = event_handle[i][j][k];
622 lum.cmd = LTTNG_UST_RELEASE;
623 ret = send_app_cmd(sock, &lum, &lur);
624 if (ret)
625 return ret;
626 }
627 memset(&lum, 0, sizeof(lum));
628 lum.handle = channel_data[i][j].handle;
629 lum.cmd = LTTNG_UST_RELEASE;
630 ret = send_app_cmd(sock, &lum, &lur);
631 if (ret)
632 return ret;
633 if (channel_data[i][j].shm_fd >= 0) {
634 ret = close(channel_data[i][j].shm_fd);
635 if (ret)
636 return ret;
637 }
638 if (channel_data[i][j].wait_fd >= 0) {
639 ret = close(channel_data[i][j].wait_fd);
640 if (ret)
641 return ret;
642 }
643 }
644
645 /* Release metadata channel */
646 ret = close_streams(sock, &metadata_stream_data[i], 1);
647 if (ret)
648 return ret;
649
650 memset(&lum, 0, sizeof(lum));
651 lum.handle = metadata_data[i].handle;
652 lum.cmd = LTTNG_UST_RELEASE;
653 ret = send_app_cmd(sock, &lum, &lur);
654 if (ret)
655 return ret;
656 if (metadata_data[i].shm_fd >= 0) {
657 ret = close(metadata_data[i].shm_fd);
658 if (ret)
659 return ret;
660 }
661 if (metadata_data[i].wait_fd >= 0) {
662 ret = close(metadata_data[i].wait_fd);
663 if (ret)
664 return ret;
665 }
666
667 /* Release session */
668 memset(&lum, 0, sizeof(lum));
669 lum.handle = session_handle[i];
670 lum.cmd = LTTNG_UST_RELEASE;
671 ret = send_app_cmd(sock, &lum, &lur);
672 if (ret)
673 return ret;
674 }
675
676 return 0;
677}
678
679/*
680 * Using fork to set umask in the child process (not multi-thread safe). We
681 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
682 * the shm and does not let everybody modify it, to ensure safety against
683 * shm_unlink) by simply letting the mmap fail and retrying after a few
684 * seconds. For global shm, everybody has rw access to it until the sessiond
685 * starts.
686 */
687static int get_wait_shm(char *shm_path, size_t mmap_size, int global)
688{
689 int wait_shm_fd, ret;
690 mode_t mode;
691
692 /* Default permissions */
693 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
694
695 /* Change owner of the shm path */
696 if (global) {
697 ret = chown(shm_path, 0, 0);
698 if (ret < 0) {
699 if (errno != ENOENT) {
700 perror("chown wait shm");
701 goto error;
702 }
703 }
704
705 /*
706 * If global session daemon, any application can register so the shm
707 * needs to be set in read-only mode for others.
708 */
709 mode |= S_IROTH;
710 } else {
711 ret = chown(shm_path, getuid(), getgid());
712 if (ret < 0) {
713 if (errno != ENOENT) {
714 perror("chown wait shm");
715 goto error;
716 }
717 }
718 }
719
720 /*
721 * Set permissions to the shm even if we did not create the shm.
722 */
723 ret = chmod(shm_path, mode);
724 if (ret < 0) {
725 if (errno != ENOENT) {
726 perror("chmod wait shm");
727 goto error;
728 }
729 }
730
731 /*
732 * We're alone in a child process, so we can modify the process-wide
733 * umask.
734 */
735 umask(~mode);
736
737 /*
738 * Try creating shm (or get rw access). We don't do an exclusive open,
739 * because we allow other processes to create+ftruncate it concurrently.
740 */
741 wait_shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, mode);
742 if (wait_shm_fd < 0) {
743 perror("shm_open wait shm");
744 goto error;
745 }
746
747 ret = ftruncate(wait_shm_fd, mmap_size);
748 if (ret < 0) {
749 perror("ftruncate wait shm");
750 exit(EXIT_FAILURE);
751 }
752
753 ret = fchmod(wait_shm_fd, mode);
754 if (ret < 0) {
755 perror("fchmod");
756 exit(EXIT_FAILURE);
757 }
758
759 printf("Got the wait shm fd %d\n", wait_shm_fd);
760
761 return wait_shm_fd;
762
763error:
764 printf("Failing to get the wait shm fd\n");
765
766 return -1;
767}
768
769int update_futex(int fd, int active)
770{
771 size_t mmap_size = sysconf(_SC_PAGE_SIZE);
772 char *wait_shm_mmap;
773 int ret;
774
775 wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
776 MAP_SHARED, fd, 0);
777 if (wait_shm_mmap == MAP_FAILED) {
778 perror("mmap");
779 goto error;
780 }
781
782 if (active) {
783 uatomic_set((int32_t *) wait_shm_mmap, 1);
784 futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
785 INT_MAX, NULL, NULL, 0);
786 } else {
787 uatomic_set((int32_t *) wait_shm_mmap, 0);
788 }
789 ret = munmap(wait_shm_mmap, mmap_size);
790 if (ret) {
791 perror("Error unmapping wait shm");
792 goto error;
793 }
794 return 0;
795error:
796 return -1;
797}
798
799/*
800 * Set open files limit to unlimited. This daemon can open a large number of
801 * file descriptors in order to consumer multiple kernel traces.
802 */
803static void set_ulimit(void)
804{
805 int ret;
806 struct rlimit lim;
807
808 /*
809 * If not root, we cannot increase our max open files. But our
810 * scope is then limited to processes from a single user.
811 */
812 if (getuid() != 0)
813 return;
814 /* The kernel does not allowed an infinite limit for open files */
815 lim.rlim_cur = 65535;
816 lim.rlim_max = 65535;
817
818 ret = setrlimit(RLIMIT_NOFILE, &lim);
819 if (ret < 0) {
820 perror("failed to set open files limit");
821 }
822}
823
824int main(int argc, char **argv)
825{
826 const char *home_dir;
827 int ret, wait_shm_fd;
828 struct sigaction act;
829 mode_t old_umask;
830
831 set_ulimit();
832
833 /* Ignore sigpipe */
834 memset(&act, 0, sizeof(act));
835 ret = sigemptyset(&act.sa_mask);
836 if (ret == -1) {
837 perror("sigemptyset");
838 return -1;
839 }
840
841 act.sa_handler = SIG_IGN;
842 ret = sigaction(SIGPIPE, &act, NULL);
843 if (ret == -1) {
844 perror("sigaction");
845 return -1;
846 }
847
848 /* Handle SIGTERM */
849 act.sa_handler = handle_signals;
850 ret = sigaction(SIGTERM, &act, NULL);
851 if (ret == -1) {
852 perror("sigaction");
853 return -1;
854 }
855 /* Handle SIGINT */
856 ret = sigaction(SIGINT, &act, NULL);
857 if (ret == -1) {
858 perror("sigaction");
859 return -1;
860 }
861
862 if (geteuid() == 0) {
863 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
864 if (ret && errno != EEXIST) {
865 perror("mkdir");
866 return -1;
867 }
868 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
869 sysconf(_SC_PAGE_SIZE), 1);
870 if (wait_shm_fd < 0) {
871 perror("global wait shm error");
872 return -1;
873 }
874 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
875 old_umask = umask(0);
876 } else {
877 snprintf(local_apps_wait_shm_path, PATH_MAX,
878 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
879 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
880 sysconf(_SC_PAGE_SIZE), 0);
881 if (wait_shm_fd < 0) {
882 perror("local wait shm error");
883 return -1;
884 }
885 home_dir = (const char *) getenv("HOME");
886 if (!home_dir) {
887 perror("getenv error");
888 return -ENOENT;
889 }
890 snprintf(apps_sock_path, PATH_MAX,
891 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
892 }
893
894 ret = lttcomm_create_unix_sock(apps_sock_path);
895 if (ret < 0) {
896 perror("create error");
897 return ret;
898 }
899 apps_socket = ret;
900
901 if (getuid() == 0) {
902 /* File permission MUST be 666 */
903 ret = chmod(apps_sock_path,
904 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
905 if (ret < 0) {
906 printf("Set file permissions failed: %s\n", apps_sock_path);
907 perror("chmod");
908 goto end;
909 }
910 umask(old_umask);
911 }
912 ret = lttcomm_listen_unix_sock(apps_socket);
913 if (ret < 0) {
914 perror("listen error");
915 return ret;
916 }
917
918 /* wake up futexes */
919 ret = update_futex(wait_shm_fd, 1);
920 if (ret) {
921 fprintf(stderr, "Error wakeup futex\n");
922 return -1;
923 }
924
925 for (;;) {
926 int sock;
927 ssize_t len;
928 struct {
929 uint32_t major;
930 uint32_t minor;
931 pid_t pid;
932 pid_t ppid;
933 uid_t uid;
934 gid_t gid;
935 char name[16]; /* Process name */
936 } reg_msg;
937 char bufname[17];
938
939 if (quit_program)
940 break;
941
942 printf("Accepting application registration\n");
943 sock = lttcomm_accept_unix_sock(apps_socket);
944 if (sock < 0) {
945 perror("accept error");
946 goto end;
947 }
948
949 /*
950 * Basic recv here to handle the very simple data
951 * that the libust send to register (reg_msg).
952 */
953 len = lttcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
954 if (len < 0 || len != sizeof(reg_msg)) {
955 perror("lttcomm_recv_unix_sock");
956 continue;
957 }
958 memcpy(bufname, reg_msg.name, 16);
959 bufname[16] = '\0';
960 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
961 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
962 reg_msg.gid, reg_msg.major, reg_msg.minor);
963 ret = send_app_msgs(sock);
964 if (ret) {
965 printf("Error in send_app_msgs.\n");
966 sleep(1);
967 }
968 close(sock);
969 }
970
971end:
972 printf("quitting.\n");
973 /* Let applications know we are not responding anymore */
974 ret = update_futex(wait_shm_fd, 0);
975 if (ret) {
976 fprintf(stderr, "Error wakeup futex\n");
977 return -1;
978 }
979
980 return 0;
981}
This page took 0.057704 seconds and 4 git commands to generate.