2 * ust-multi-test.c - single-proces, multi-session, multi-channel, multi-event UST tracing
4 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License only.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #define _LARGEFILE64_SOURCE
33 #include <sys/resource.h>
34 #include <sys/socket.h>
37 #include <sys/types.h>
40 #include <urcu/futex.h>
41 #include <urcu/uatomic.h>
44 #include <lttng/ust-error.h>
45 #include <../../libringbuffer/backend.h>
46 #include <../../libringbuffer/frontend.h>
47 #include "../../liblttng-ust/compat.h" /* For ENODATA */
51 #define MAX_NR_STREAMS 64
54 const char *evname
[] = {
55 "ust_tests_hello_tptest",
56 "ust_tests_hello_tptest_sighandler",
57 "ust_tests_hello_dontexist",
60 static int session_handle
[NR_SESSIONS
];
61 static struct lttng_ust_object_data metadata_stream_data
[NR_SESSIONS
];
62 static struct lttng_ust_object_data metadata_data
[NR_SESSIONS
];
63 static struct lttng_ust_object_data channel_data
[NR_SESSIONS
][NR_CHANNELS
];
64 static struct lttng_ust_object_data stream_data
[NR_SESSIONS
][NR_CHANNELS
][MAX_NR_STREAMS
];
65 static int event_handle
[NR_SESSIONS
][NR_CHANNELS
][NR_EVENTS
];
67 static int apps_socket
= -1;
68 static char apps_sock_path
[PATH_MAX
];
69 static char local_apps_wait_shm_path
[PATH_MAX
];
71 static volatile int quit_program
;
73 static void handle_signals(int signo
)
79 int open_streams(int sock
, int channel_handle
, struct lttng_ust_object_data
*stream_datas
,
85 struct ustcomm_ust_msg lum
;
86 struct ustcomm_ust_reply lur
;
88 memset(&lum
, 0, sizeof(lum
));
89 lum
.handle
= channel_handle
;
90 lum
.cmd
= LTTNG_UST_STREAM
;
91 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
94 stream_datas
[k
].handle
= lur
.ret_val
;
95 printf("received stream handle %u\n",
96 stream_datas
[k
].handle
);
97 if (lur
.ret_code
== LTTNG_UST_OK
) {
100 stream_datas
[k
].memory_map_size
= lur
.u
.stream
.memory_map_size
;
102 len
= ustcomm_recv_fd(sock
);
105 stream_datas
[k
].shm_fd
= len
;
107 len
= ustcomm_recv_fd(sock
);
110 stream_datas
[k
].wait_fd
= len
;
114 if (ret
== -LTTNG_UST_ERR_NOENT
)
123 int close_streams(int sock
, struct lttng_ust_object_data
*stream_datas
, int nr_check
)
127 for (k
= 0; k
< nr_check
; k
++) {
128 struct ustcomm_ust_msg lum
;
129 struct ustcomm_ust_reply lur
;
131 if (!stream_datas
[k
].handle
)
133 memset(&lum
, 0, sizeof(lum
));
134 lum
.handle
= stream_datas
[k
].handle
;
135 lum
.cmd
= LTTNG_UST_RELEASE
;
136 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
138 printf("Error closing stream\n");
141 if (stream_datas
[k
].shm_fd
>= 0) {
142 ret
= close(stream_datas
[k
].shm_fd
);
144 printf("Error closing stream shm_fd\n");
148 if (stream_datas
[k
].wait_fd
>= 0) {
149 ret
= close(stream_datas
[k
].wait_fd
);
151 printf("Error closing stream wait_fd\n");
160 struct lttng_ust_shm_handle
*map_channel(struct lttng_ust_object_data
*chan_data
,
161 struct lttng_ust_object_data
*stream_datas
, int nr_check
)
163 struct lttng_ust_shm_handle
*handle
;
164 struct channel
*chan
;
167 /* map metadata channel */
168 handle
= channel_handle_create(chan_data
->shm_fd
,
170 chan_data
->memory_map_size
);
172 printf("create handle error\n");
175 chan_data
->shm_fd
= -1;
176 chan_data
->wait_fd
= -1;
177 chan
= shmp(handle
, handle
->chan
);
179 for (k
= 0; k
< nr_check
; k
++) {
180 struct lttng_ust_object_data
*stream_data
= &stream_datas
[k
];
182 if (!stream_data
->handle
)
185 ret
= channel_handle_add_stream(handle
,
187 stream_data
->wait_fd
,
188 stream_data
->memory_map_size
);
190 printf("add stream error\n");
193 stream_data
->shm_fd
= -1;
194 stream_data
->wait_fd
= -1;
199 channel_destroy(chan
, handle
, 1);
204 void unmap_channel(struct lttng_ust_shm_handle
*handle
)
206 struct channel
*chan
;
208 chan
= shmp(handle
, handle
->chan
);
210 channel_destroy(chan
, handle
, 1);
214 int consume_stream(struct lttng_ust_shm_handle
*handle
, int cpu
, char *outfile
)
216 struct channel
*chan
;
217 struct lttng_ust_lib_ring_buffer
*buf
;
219 int *shm_fd
, *wait_fd
;
220 uint64_t *memory_map_size
;
222 chan
= shmp(handle
, handle
->chan
);
225 buf
= channel_get_ring_buffer(&chan
->backend
.config
,
226 chan
, cpu
, handle
, &shm_fd
, &wait_fd
, &memory_map_size
);
229 ret
= lib_ring_buffer_open_read(buf
, handle
, 1);
235 outfd
= open(outfile
, O_WRONLY
| O_CREAT
| O_TRUNC
,
236 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
238 perror("open output");
242 printf("Waiting for buffer data for %s\n", outfile
);
244 unsigned long read_size
;
245 unsigned long copy_size
;
248 ret
= lib_ring_buffer_get_next_subbuf(buf
, handle
);
249 printf("get next ret %d\n", ret
);
252 if (ret
== -EAGAIN
) {
257 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret
);
260 read_size
= lib_ring_buffer_get_read_data_size(
261 &chan
->backend
.config
, buf
, handle
);
262 read_size
= PAGE_ALIGN(read_size
);
263 ptr
= lib_ring_buffer_read_offset_address(
264 &buf
->backend
, 0, handle
);
265 printf("WRITE: copy %lu bytes\n", read_size
);
266 copy_size
= write(outfd
, ptr
, read_size
);
267 if (copy_size
< read_size
) {
268 printf("write issue: copied %lu, expected %lu\n", copy_size
, read_size
);
270 lib_ring_buffer_put_next_subbuf(buf
, handle
);
280 lib_ring_buffer_release_read(buf
, handle
, 1);
285 int consume_buffers(void)
290 for (i
= 0; i
< NR_SESSIONS
; i
++) {
291 char pathname
[PATH_MAX
];
292 struct lttng_ust_shm_handle
*handle
;
294 snprintf(pathname
, PATH_MAX
- 1, "/tmp/testtrace%u", i
);
295 old_umask
= umask(0);
296 ret
= mkdir(pathname
, S_IRWXU
| S_IRWXG
);
297 if (ret
&& errno
!= EEXIST
) {
305 handle
= map_channel(&metadata_data
[i
],
306 &metadata_stream_data
[i
], 1);
309 snprintf(pathname
, PATH_MAX
- 1,
310 "/tmp/testtrace%u/metadata", i
);
311 ret
= consume_stream(handle
, -1, pathname
);
312 if (ret
&& ret
!= -ENOENT
) {
313 printf("Error in consume_stream\n");
316 unmap_channel(handle
);
318 /* copy binary data */
319 for (j
= 0; j
< NR_CHANNELS
; j
++) {
320 handle
= map_channel(&channel_data
[i
][j
],
321 stream_data
[i
][j
], MAX_NR_STREAMS
);
324 for (k
= 0; k
< MAX_NR_STREAMS
; k
++) {
325 snprintf(pathname
, PATH_MAX
- 1,
326 "/tmp/testtrace%u/data_%u", i
, k
);
327 ret
= consume_stream(handle
, k
, pathname
);
328 if (ret
&& ret
!= -ENOENT
) {
329 printf("Error in consume_stream\n");
333 unmap_channel(handle
);
340 int send_app_msgs(int sock
)
342 struct ustcomm_ust_msg lum
;
343 struct ustcomm_ust_reply lur
;
346 for (i
= 0; i
< NR_SESSIONS
; i
++) {
348 memset(&lum
, 0, sizeof(lum
));
349 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
350 lum
.cmd
= LTTNG_UST_SESSION
;
351 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
354 session_handle
[i
] = lur
.ret_val
;
355 printf("received session handle %u\n", session_handle
[i
]);
357 /* Create metadata channel */
358 memset(&lum
, 0, sizeof(lum
));
359 lum
.handle
= session_handle
[i
];
360 lum
.cmd
= LTTNG_UST_METADATA
;
361 lum
.u
.channel
.overwrite
= 0;
362 lum
.u
.channel
.subbuf_size
= 32768;
363 lum
.u
.channel
.num_subbuf
= 4;
364 lum
.u
.channel
.switch_timer_interval
= 0;
365 lum
.u
.channel
.read_timer_interval
= 0;
366 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
367 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
370 metadata_data
[i
].handle
= lur
.ret_val
;
371 printf("received metadata handle %u\n", metadata_data
[i
].handle
);
372 if (lur
.ret_code
== LTTNG_UST_OK
) {
375 metadata_data
[i
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
377 len
= ustcomm_recv_fd(sock
);
380 metadata_data
[i
].shm_fd
= len
;
382 len
= ustcomm_recv_fd(sock
);
385 metadata_data
[i
].wait_fd
= len
;
388 ret
= open_streams(sock
, metadata_data
[i
].handle
,
389 &metadata_stream_data
[i
], 1);
391 printf("Error in open_streams\n");
395 /* Create channels */
396 for (j
= 0; j
< NR_CHANNELS
; j
++) {
397 memset(&lum
, 0, sizeof(lum
));
398 lum
.handle
= session_handle
[i
];
399 lum
.cmd
= LTTNG_UST_CHANNEL
;
400 //lum.u.channel.overwrite = 0;
401 lum
.u
.channel
.overwrite
= 1;
402 lum
.u
.channel
.subbuf_size
= 32768;
403 lum
.u
.channel
.num_subbuf
= 8;
404 //lum.u.channel.num_subbuf = 4;
405 //lum.u.channel.num_subbuf = 2;
406 lum
.u
.channel
.switch_timer_interval
= 0;
407 lum
.u
.channel
.read_timer_interval
= 0;
408 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
409 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
412 channel_data
[i
][j
].handle
= lur
.ret_val
;
413 printf("received channel handle %u\n", channel_data
[i
][j
].handle
);
414 if (lur
.ret_code
== LTTNG_UST_OK
) {
417 channel_data
[i
][j
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
419 len
= ustcomm_recv_fd(sock
);
422 channel_data
[i
][j
].shm_fd
= len
;
424 len
= ustcomm_recv_fd(sock
);
427 channel_data
[i
][j
].wait_fd
= len
;
431 for (k
= 0; k
< NR_EVENTS
; k
++) {
432 memset(&lum
, 0, sizeof(lum
));
433 lum
.handle
= channel_data
[i
][j
].handle
;
434 lum
.cmd
= LTTNG_UST_EVENT
;
435 strncpy(lum
.u
.event
.name
, evname
[k
],
436 LTTNG_UST_SYM_NAME_LEN
);
437 lum
.u
.event
.instrumentation
= LTTNG_UST_TRACEPOINT
;
438 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
441 event_handle
[i
][j
][k
] = lur
.ret_val
;
442 printf("received event handle %u\n", event_handle
[i
][j
][k
]);
445 /* Get references to channel streams */
446 ret
= open_streams(sock
, channel_data
[i
][j
].handle
,
447 stream_data
[i
][j
], MAX_NR_STREAMS
);
449 printf("Error in open_streams\n");
454 memset(&lum
, 0, sizeof(lum
));
455 lum
.handle
= session_handle
[i
];
456 lum
.cmd
= LTTNG_UST_SESSION_START
;
457 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
460 printf("Session handle %u started.\n", session_handle
[i
]);
463 /* Tell application registration is done */
464 memset(&lum
, 0, sizeof(lum
));
465 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
466 lum
.cmd
= LTTNG_UST_REGISTER_DONE
;
467 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
470 printf("Registration done acknowledged.\n");
474 ret
= consume_buffers();
476 printf("Error in consume_buffers\n");
480 for (i
= 0; i
< NR_SESSIONS
; i
++) {
481 /* Release channels */
482 for (j
= 0; j
< NR_CHANNELS
; j
++) {
483 /* Release streams */
484 ret
= close_streams(sock
, stream_data
[i
][j
],
490 for (k
= 0; k
< NR_EVENTS
; k
++) {
491 memset(&lum
, 0, sizeof(lum
));
492 lum
.handle
= event_handle
[i
][j
][k
];
493 lum
.cmd
= LTTNG_UST_RELEASE
;
494 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
498 memset(&lum
, 0, sizeof(lum
));
499 lum
.handle
= channel_data
[i
][j
].handle
;
500 lum
.cmd
= LTTNG_UST_RELEASE
;
501 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
504 if (channel_data
[i
][j
].shm_fd
>= 0) {
505 ret
= close(channel_data
[i
][j
].shm_fd
);
509 if (channel_data
[i
][j
].wait_fd
>= 0) {
510 ret
= close(channel_data
[i
][j
].wait_fd
);
516 /* Release metadata channel */
517 ret
= close_streams(sock
, &metadata_stream_data
[i
], 1);
521 memset(&lum
, 0, sizeof(lum
));
522 lum
.handle
= metadata_data
[i
].handle
;
523 lum
.cmd
= LTTNG_UST_RELEASE
;
524 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
527 if (metadata_data
[i
].shm_fd
>= 0) {
528 ret
= close(metadata_data
[i
].shm_fd
);
532 if (metadata_data
[i
].wait_fd
>= 0) {
533 ret
= close(metadata_data
[i
].wait_fd
);
538 /* Release session */
539 memset(&lum
, 0, sizeof(lum
));
540 lum
.handle
= session_handle
[i
];
541 lum
.cmd
= LTTNG_UST_RELEASE
;
542 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
551 * Using fork to set umask in the child process (not multi-thread safe). We
552 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
553 * the shm and does not let everybody modify it, to ensure safety against
554 * shm_unlink) by simply letting the mmap fail and retrying after a few
555 * seconds. For global shm, everybody has rw access to it until the sessiond
558 static int get_wait_shm(char *shm_path
, size_t mmap_size
, int global
)
560 int wait_shm_fd
, ret
;
563 /* Default permissions */
564 mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
566 /* Change owner of the shm path */
568 ret
= chown(shm_path
, 0, 0);
570 if (errno
!= ENOENT
) {
571 perror("chown wait shm");
577 * If global session daemon, any application can register so the shm
578 * needs to be set in read-only mode for others.
582 ret
= chown(shm_path
, getuid(), getgid());
584 if (errno
!= ENOENT
) {
585 perror("chown wait shm");
592 * Set permissions to the shm even if we did not create the shm.
594 ret
= chmod(shm_path
, mode
);
596 if (errno
!= ENOENT
) {
597 perror("chmod wait shm");
603 * We're alone in a child process, so we can modify the process-wide
609 * Try creating shm (or get rw access). We don't do an exclusive open,
610 * because we allow other processes to create+ftruncate it concurrently.
612 wait_shm_fd
= shm_open(shm_path
, O_RDWR
| O_CREAT
, mode
);
613 if (wait_shm_fd
< 0) {
614 perror("shm_open wait shm");
618 ret
= ftruncate(wait_shm_fd
, mmap_size
);
620 perror("ftruncate wait shm");
624 ret
= fchmod(wait_shm_fd
, mode
);
630 printf("Got the wait shm fd %d\n", wait_shm_fd
);
635 printf("Failing to get the wait shm fd\n");
640 int update_futex(int fd
, int active
)
646 page_size
= sysconf(_SC_PAGE_SIZE
);
647 if (page_size
<= 0) {
651 perror("Error in sysconf(_SC_PAGE_SIZE)");
654 wait_shm_mmap
= mmap(NULL
, page_size
, PROT_READ
| PROT_WRITE
,
656 if (wait_shm_mmap
== MAP_FAILED
) {
662 uatomic_set((int32_t *) wait_shm_mmap
, 1);
663 if (futex_async((int32_t *) wait_shm_mmap
, FUTEX_WAKE
,
664 INT_MAX
, NULL
, NULL
, 0) < 0) {
665 perror("futex_async");
669 uatomic_set((int32_t *) wait_shm_mmap
, 0);
671 ret
= munmap(wait_shm_mmap
, page_size
);
673 perror("Error unmapping wait shm");
682 * Set open files limit to unlimited. This daemon can open a large number of
683 * file descriptors in order to consumer multiple kernel traces.
685 static void set_ulimit(void)
691 * If not root, we cannot increase our max open files. But our
692 * scope is then limited to processes from a single user.
696 /* The kernel does not allowed an infinite limit for open files */
697 lim
.rlim_cur
= 65535;
698 lim
.rlim_max
= 65535;
700 ret
= setrlimit(RLIMIT_NOFILE
, &lim
);
702 perror("failed to set open files limit");
706 int main(int argc
, char **argv
)
708 const char *home_dir
;
709 char home_rundir
[PATH_MAX
];
711 int ret
, wait_shm_fd
;
712 struct sigaction act
;
713 mode_t old_umask
= 0;
719 memset(&act
, 0, sizeof(act
));
720 ret
= sigemptyset(&act
.sa_mask
);
722 perror("sigemptyset");
726 act
.sa_handler
= SIG_IGN
;
727 ret
= sigaction(SIGPIPE
, &act
, NULL
);
734 act
.sa_handler
= handle_signals
;
735 ret
= sigaction(SIGTERM
, &act
, NULL
);
741 ret
= sigaction(SIGINT
, &act
, NULL
);
747 page_size
= sysconf(_SC_PAGE_SIZE
);
748 if (page_size
<= 0) {
752 perror("Error in sysconf(_SC_PAGE_SIZE)");
756 if (geteuid() == 0) {
757 ret
= mkdir(LTTNG_RUNDIR
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
758 if (ret
&& errno
!= EEXIST
) {
762 wait_shm_fd
= get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH
,
764 if (wait_shm_fd
< 0) {
765 perror("global wait shm error");
768 strcpy(apps_sock_path
, DEFAULT_GLOBAL_APPS_UNIX_SOCK
);
769 old_umask
= umask(0);
771 home_dir
= (const char *) getenv("HOME");
773 perror("getenv error");
777 snprintf(home_rundir
, PATH_MAX
,
778 LTTNG_HOME_RUNDIR
, home_dir
);
780 ret
= mkdir(home_rundir
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
781 if (ret
&& errno
!= EEXIST
) {
786 snprintf(local_apps_wait_shm_path
, PATH_MAX
,
787 DEFAULT_HOME_APPS_WAIT_SHM_PATH
, getuid());
788 wait_shm_fd
= get_wait_shm(local_apps_wait_shm_path
,
790 if (wait_shm_fd
< 0) {
791 perror("local wait shm error");
794 snprintf(apps_sock_path
, PATH_MAX
,
795 DEFAULT_HOME_APPS_UNIX_SOCK
, home_dir
);
798 ret
= ustcomm_create_unix_sock(apps_sock_path
);
800 perror("create error");
806 /* File permission MUST be 666 */
807 ret
= chmod(apps_sock_path
,
808 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
810 printf("Set file permissions failed: %s\n", apps_sock_path
);
816 ret
= ustcomm_listen_unix_sock(apps_socket
);
818 perror("listen error");
822 /* wake up futexes */
823 ret
= update_futex(wait_shm_fd
, 1);
825 fprintf(stderr
, "Error wakeup futex\n");
839 uint32_t bits_per_long
;
840 char name
[16]; /* Process name */
847 printf("Accepting application registration\n");
848 sock
= ustcomm_accept_unix_sock(apps_socket
);
850 perror("accept error");
855 * Basic recv here to handle the very simple data
856 * that the libust send to register (reg_msg).
858 len
= ustcomm_recv_unix_sock(sock
, ®_msg
, sizeof(reg_msg
));
859 if (len
< 0 || len
!= sizeof(reg_msg
)) {
860 perror("ustcomm_recv_unix_sock");
863 memcpy(bufname
, reg_msg
.name
, 16);
865 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
866 bufname
, reg_msg
.pid
, reg_msg
.ppid
, reg_msg
.uid
,
867 reg_msg
.gid
, reg_msg
.major
, reg_msg
.minor
);
868 ret
= send_app_msgs(sock
);
870 printf("Error in send_app_msgs.\n");
877 printf("quitting.\n");
878 /* Let applications know we are not responding anymore */
879 ret
= update_futex(wait_shm_fd
, 0);
881 fprintf(stderr
, "Error wakeup futex\n");
886 printf("Removing %s directory\n", home_rundir
);
887 ret
= asprintf(&cmd
, "rm -rf %s", home_rundir
);
889 printf("asprintf failed. Something is really wrong!\n");
893 /* Remove lttng run directory */
896 printf("Unable to clean %s\n", home_rundir
);