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 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.
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
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.
21 #define _LARGEFILE64_SOURCE
29 #include <sys/types.h>
34 #include <urcu/futex.h>
35 #include <urcu/uatomic.h>
37 #include <sys/socket.h>
39 #include "lttng-ust-comm.h"
40 #include <../../libringbuffer/backend.h>
41 #include <../../libringbuffer/frontend.h>
45 #define MAX_NR_STREAMS 64
48 const char *evname
[] = {
49 "ust_tests_hello_tptest",
50 "ust_tests_hello_tptest_sighandler",
51 "ust_tests_hello_dontexist",
58 uint64_t memory_map_size
;
61 static int session_handle
[NR_SESSIONS
];
62 static struct object_data metadata_stream_data
[NR_SESSIONS
];
63 static struct object_data metadata_data
[NR_SESSIONS
];
64 static struct object_data channel_data
[NR_SESSIONS
][NR_CHANNELS
];
65 static struct object_data stream_data
[NR_SESSIONS
][NR_CHANNELS
][MAX_NR_STREAMS
];
66 static int event_handle
[NR_SESSIONS
][NR_CHANNELS
][NR_EVENTS
];
68 static int apps_socket
= -1;
69 static char apps_sock_path
[PATH_MAX
];
70 static char local_apps_wait_shm_path
[PATH_MAX
];
72 static volatile int quit_program
;
74 static void handle_signals(int signo
)
80 int open_streams(int sock
, int channel_handle
, struct object_data
*stream_datas
,
86 struct ustcomm_ust_msg lum
;
87 struct ustcomm_ust_reply lur
;
89 memset(&lum
, 0, sizeof(lum
));
90 lum
.handle
= channel_handle
;
91 lum
.cmd
= LTTNG_UST_STREAM
;
92 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
95 stream_datas
[k
].handle
= lur
.ret_val
;
96 printf("received stream handle %u\n",
97 stream_datas
[k
].handle
);
98 if (lur
.ret_code
== USTCOMM_OK
) {
101 stream_datas
[k
].memory_map_size
= lur
.u
.stream
.memory_map_size
;
103 len
= ustcomm_recv_fd(sock
);
106 stream_datas
[k
].shm_fd
= len
;
108 len
= ustcomm_recv_fd(sock
);
111 stream_datas
[k
].wait_fd
= len
;
124 int close_streams(int sock
, struct object_data
*stream_datas
, int nr_check
)
128 for (k
= 0; k
< nr_check
; k
++) {
129 struct ustcomm_ust_msg lum
;
130 struct ustcomm_ust_reply lur
;
132 if (!stream_datas
[k
].handle
)
134 memset(&lum
, 0, sizeof(lum
));
135 lum
.handle
= stream_datas
[k
].handle
;
136 lum
.cmd
= LTTNG_UST_RELEASE
;
137 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
139 printf("Error closing stream\n");
142 if (stream_datas
[k
].shm_fd
>= 0) {
143 ret
= close(stream_datas
[k
].shm_fd
);
145 printf("Error closing stream shm_fd\n");
149 if (stream_datas
[k
].wait_fd
>= 0) {
150 ret
= close(stream_datas
[k
].wait_fd
);
152 printf("Error closing stream wait_fd\n");
161 struct shm_handle
*map_channel(struct object_data
*chan_data
,
162 struct object_data
*stream_datas
, int nr_check
)
164 struct shm_handle
*handle
;
165 struct channel
*chan
;
168 /* map metadata channel */
169 handle
= channel_handle_create(chan_data
->shm_fd
,
171 chan_data
->memory_map_size
);
173 printf("create handle error\n");
176 chan_data
->shm_fd
= -1;
177 chan_data
->wait_fd
= -1;
178 chan
= shmp(handle
, handle
->chan
);
180 for (k
= 0; k
< nr_check
; k
++) {
181 struct object_data
*stream_data
= &stream_datas
[k
];
183 if (!stream_data
->handle
)
186 ret
= channel_handle_add_stream(handle
,
188 stream_data
->wait_fd
,
189 stream_data
->memory_map_size
);
191 printf("add stream error\n");
194 stream_data
->shm_fd
= -1;
195 stream_data
->wait_fd
= -1;
200 channel_destroy(chan
, handle
, 1);
205 void unmap_channel(struct shm_handle
*handle
)
207 struct channel
*chan
;
209 chan
= shmp(handle
, handle
->chan
);
211 channel_destroy(chan
, handle
, 1);
215 int consume_stream(struct shm_handle
*handle
, int cpu
, char *outfile
)
217 struct channel
*chan
;
218 struct lib_ring_buffer
*buf
;
221 uint64_t memory_map_size
;
223 chan
= shmp(handle
, handle
->chan
);
226 buf
= channel_get_ring_buffer(&chan
->backend
.config
,
227 chan
, cpu
, handle
, &shm_fd
, &wait_fd
, &memory_map_size
);
230 ret
= lib_ring_buffer_open_read(buf
, handle
, 1);
236 outfd
= open(outfile
, O_WRONLY
| O_CREAT
| O_LARGEFILE
| O_TRUNC
,
237 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
239 perror("open output");
243 printf("Waiting for buffer data for %s\n", outfile
);
245 unsigned long read_size
;
246 unsigned long copy_size
;
249 ret
= lib_ring_buffer_get_next_subbuf(buf
, handle
);
250 printf("get next ret %d\n", ret
);
253 if (ret
== -EAGAIN
) {
258 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret
);
261 read_size
= lib_ring_buffer_get_read_data_size(
262 &chan
->backend
.config
, buf
, handle
);
263 read_size
= PAGE_ALIGN(read_size
);
264 ptr
= lib_ring_buffer_read_offset_address(
265 &buf
->backend
, 0, handle
);
266 printf("WRITE: copy %lu bytes\n", read_size
);
267 copy_size
= write(outfd
, ptr
, read_size
);
268 if (copy_size
< read_size
) {
269 printf("write issue: copied %zd, expected %lu\n", copy_size
, read_size
);
271 lib_ring_buffer_put_next_subbuf(buf
, handle
);
281 lib_ring_buffer_release_read(buf
, handle
, 1);
286 int consume_buffers(void)
291 for (i
= 0; i
< NR_SESSIONS
; i
++) {
292 char pathname
[PATH_MAX
];
293 struct shm_handle
*handle
;
295 snprintf(pathname
, PATH_MAX
- 1, "/tmp/testtrace%u", i
);
296 old_umask
= umask(0);
297 ret
= mkdir(pathname
, S_IRWXU
| S_IRWXG
);
298 if (ret
&& errno
!= EEXIST
) {
306 handle
= map_channel(&metadata_data
[i
],
307 &metadata_stream_data
[i
], 1);
310 snprintf(pathname
, PATH_MAX
- 1,
311 "/tmp/testtrace%u/metadata", i
);
312 ret
= consume_stream(handle
, -1, pathname
);
313 if (ret
&& ret
!= -ENOENT
) {
314 printf("Error in consume_stream\n");
317 unmap_channel(handle
);
319 /* copy binary data */
320 for (j
= 0; j
< NR_CHANNELS
; j
++) {
321 handle
= map_channel(&channel_data
[i
][j
],
322 stream_data
[i
][j
], MAX_NR_STREAMS
);
325 for (k
= 0; k
< MAX_NR_STREAMS
; k
++) {
326 snprintf(pathname
, PATH_MAX
- 1,
327 "/tmp/testtrace%u/data_%u", i
, k
);
328 ret
= consume_stream(handle
, k
, pathname
);
329 if (ret
&& ret
!= -ENOENT
) {
330 printf("Error in consume_stream\n");
334 unmap_channel(handle
);
341 int send_app_msgs(int sock
)
343 struct ustcomm_ust_msg lum
;
344 struct ustcomm_ust_reply lur
;
347 for (i
= 0; i
< NR_SESSIONS
; i
++) {
349 memset(&lum
, 0, sizeof(lum
));
350 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
351 lum
.cmd
= LTTNG_UST_SESSION
;
352 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
355 session_handle
[i
] = lur
.ret_val
;
356 printf("received session handle %u\n", session_handle
[i
]);
358 /* Create metadata channel */
359 memset(&lum
, 0, sizeof(lum
));
360 lum
.handle
= session_handle
[i
];
361 lum
.cmd
= LTTNG_UST_METADATA
;
362 lum
.u
.channel
.overwrite
= 0;
363 lum
.u
.channel
.subbuf_size
= 32768;
364 lum
.u
.channel
.num_subbuf
= 4;
365 lum
.u
.channel
.switch_timer_interval
= 0;
366 lum
.u
.channel
.read_timer_interval
= 0;
367 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
368 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
371 metadata_data
[i
].handle
= lur
.ret_val
;
372 printf("received metadata handle %u\n", metadata_data
[i
].handle
);
373 if (lur
.ret_code
== USTCOMM_OK
) {
376 metadata_data
[i
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
378 len
= ustcomm_recv_fd(sock
);
381 metadata_data
[i
].shm_fd
= len
;
383 len
= ustcomm_recv_fd(sock
);
386 metadata_data
[i
].wait_fd
= len
;
389 ret
= open_streams(sock
, metadata_data
[i
].handle
,
390 &metadata_stream_data
[i
], 1);
392 printf("Error in open_streams\n");
396 /* Create channels */
397 for (j
= 0; j
< NR_CHANNELS
; j
++) {
398 memset(&lum
, 0, sizeof(lum
));
399 lum
.handle
= session_handle
[i
];
400 lum
.cmd
= LTTNG_UST_CHANNEL
;
401 //lum.u.channel.overwrite = 0;
402 lum
.u
.channel
.overwrite
= 1;
403 lum
.u
.channel
.subbuf_size
= 32768;
404 lum
.u
.channel
.num_subbuf
= 8;
405 //lum.u.channel.num_subbuf = 4;
406 //lum.u.channel.num_subbuf = 2;
407 lum
.u
.channel
.switch_timer_interval
= 0;
408 lum
.u
.channel
.read_timer_interval
= 0;
409 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
410 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
413 channel_data
[i
][j
].handle
= lur
.ret_val
;
414 printf("received channel handle %u\n", channel_data
[i
][j
].handle
);
415 if (lur
.ret_code
== USTCOMM_OK
) {
418 channel_data
[i
][j
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
420 len
= ustcomm_recv_fd(sock
);
423 channel_data
[i
][j
].shm_fd
= len
;
425 len
= ustcomm_recv_fd(sock
);
428 channel_data
[i
][j
].wait_fd
= len
;
432 for (k
= 0; k
< NR_EVENTS
; k
++) {
433 memset(&lum
, 0, sizeof(lum
));
434 lum
.handle
= channel_data
[i
][j
].handle
;
435 lum
.cmd
= LTTNG_UST_EVENT
;
436 strncpy(lum
.u
.event
.name
, evname
[k
],
437 LTTNG_UST_SYM_NAME_LEN
);
438 lum
.u
.event
.instrumentation
= LTTNG_UST_TRACEPOINT
;
439 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
442 event_handle
[i
][j
][k
] = lur
.ret_val
;
443 printf("received event handle %u\n", event_handle
[i
][j
][k
]);
446 /* Get references to channel streams */
447 ret
= open_streams(sock
, channel_data
[i
][j
].handle
,
448 stream_data
[i
][j
], MAX_NR_STREAMS
);
450 printf("Error in open_streams\n");
455 memset(&lum
, 0, sizeof(lum
));
456 lum
.handle
= session_handle
[i
];
457 lum
.cmd
= LTTNG_UST_SESSION_START
;
458 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
461 printf("Session handle %u started.\n", session_handle
[i
]);
464 /* Tell application registration is done */
465 memset(&lum
, 0, sizeof(lum
));
466 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
467 lum
.cmd
= LTTNG_UST_REGISTER_DONE
;
468 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
471 printf("Registration done acknowledged.\n");
475 ret
= consume_buffers();
477 printf("Error in consume_buffers\n");
481 for (i
= 0; i
< NR_SESSIONS
; i
++) {
482 /* Release channels */
483 for (j
= 0; j
< NR_CHANNELS
; j
++) {
484 /* Release streams */
485 ret
= close_streams(sock
, stream_data
[i
][j
],
491 for (k
= 0; k
< NR_EVENTS
; k
++) {
492 memset(&lum
, 0, sizeof(lum
));
493 lum
.handle
= event_handle
[i
][j
][k
];
494 lum
.cmd
= LTTNG_UST_RELEASE
;
495 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
499 memset(&lum
, 0, sizeof(lum
));
500 lum
.handle
= channel_data
[i
][j
].handle
;
501 lum
.cmd
= LTTNG_UST_RELEASE
;
502 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
505 if (channel_data
[i
][j
].shm_fd
>= 0) {
506 ret
= close(channel_data
[i
][j
].shm_fd
);
510 if (channel_data
[i
][j
].wait_fd
>= 0) {
511 ret
= close(channel_data
[i
][j
].wait_fd
);
517 /* Release metadata channel */
518 ret
= close_streams(sock
, &metadata_stream_data
[i
], 1);
522 memset(&lum
, 0, sizeof(lum
));
523 lum
.handle
= metadata_data
[i
].handle
;
524 lum
.cmd
= LTTNG_UST_RELEASE
;
525 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
528 if (metadata_data
[i
].shm_fd
>= 0) {
529 ret
= close(metadata_data
[i
].shm_fd
);
533 if (metadata_data
[i
].wait_fd
>= 0) {
534 ret
= close(metadata_data
[i
].wait_fd
);
539 /* Release session */
540 memset(&lum
, 0, sizeof(lum
));
541 lum
.handle
= session_handle
[i
];
542 lum
.cmd
= LTTNG_UST_RELEASE
;
543 ret
= ustcomm_send_app_cmd(sock
, &lum
, &lur
);
552 * Using fork to set umask in the child process (not multi-thread safe). We
553 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
554 * the shm and does not let everybody modify it, to ensure safety against
555 * shm_unlink) by simply letting the mmap fail and retrying after a few
556 * seconds. For global shm, everybody has rw access to it until the sessiond
559 static int get_wait_shm(char *shm_path
, size_t mmap_size
, int global
)
561 int wait_shm_fd
, ret
;
564 /* Default permissions */
565 mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
567 /* Change owner of the shm path */
569 ret
= chown(shm_path
, 0, 0);
571 if (errno
!= ENOENT
) {
572 perror("chown wait shm");
578 * If global session daemon, any application can register so the shm
579 * needs to be set in read-only mode for others.
583 ret
= chown(shm_path
, getuid(), getgid());
585 if (errno
!= ENOENT
) {
586 perror("chown wait shm");
593 * Set permissions to the shm even if we did not create the shm.
595 ret
= chmod(shm_path
, mode
);
597 if (errno
!= ENOENT
) {
598 perror("chmod wait shm");
604 * We're alone in a child process, so we can modify the process-wide
610 * Try creating shm (or get rw access). We don't do an exclusive open,
611 * because we allow other processes to create+ftruncate it concurrently.
613 wait_shm_fd
= shm_open(shm_path
, O_RDWR
| O_CREAT
, mode
);
614 if (wait_shm_fd
< 0) {
615 perror("shm_open wait shm");
619 ret
= ftruncate(wait_shm_fd
, mmap_size
);
621 perror("ftruncate wait shm");
625 ret
= fchmod(wait_shm_fd
, mode
);
631 printf("Got the wait shm fd %d\n", wait_shm_fd
);
636 printf("Failing to get the wait shm fd\n");
641 int update_futex(int fd
, int active
)
643 size_t mmap_size
= sysconf(_SC_PAGE_SIZE
);
647 wait_shm_mmap
= mmap(NULL
, mmap_size
, PROT_READ
| PROT_WRITE
,
649 if (wait_shm_mmap
== MAP_FAILED
) {
655 uatomic_set((int32_t *) wait_shm_mmap
, 1);
656 futex_async((int32_t *) wait_shm_mmap
, FUTEX_WAKE
,
657 INT_MAX
, NULL
, NULL
, 0);
659 uatomic_set((int32_t *) wait_shm_mmap
, 0);
661 ret
= munmap(wait_shm_mmap
, mmap_size
);
663 perror("Error unmapping wait shm");
672 * Set open files limit to unlimited. This daemon can open a large number of
673 * file descriptors in order to consumer multiple kernel traces.
675 static void set_ulimit(void)
681 * If not root, we cannot increase our max open files. But our
682 * scope is then limited to processes from a single user.
686 /* The kernel does not allowed an infinite limit for open files */
687 lim
.rlim_cur
= 65535;
688 lim
.rlim_max
= 65535;
690 ret
= setrlimit(RLIMIT_NOFILE
, &lim
);
692 perror("failed to set open files limit");
696 int main(int argc
, char **argv
)
698 const char *home_dir
;
699 int ret
, wait_shm_fd
;
700 struct sigaction act
;
701 mode_t old_umask
= 0;
706 memset(&act
, 0, sizeof(act
));
707 ret
= sigemptyset(&act
.sa_mask
);
709 perror("sigemptyset");
713 act
.sa_handler
= SIG_IGN
;
714 ret
= sigaction(SIGPIPE
, &act
, NULL
);
721 act
.sa_handler
= handle_signals
;
722 ret
= sigaction(SIGTERM
, &act
, NULL
);
728 ret
= sigaction(SIGINT
, &act
, NULL
);
734 if (geteuid() == 0) {
735 ret
= mkdir(LTTNG_RUNDIR
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
736 if (ret
&& errno
!= EEXIST
) {
740 wait_shm_fd
= get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH
,
741 sysconf(_SC_PAGE_SIZE
), 1);
742 if (wait_shm_fd
< 0) {
743 perror("global wait shm error");
746 strcpy(apps_sock_path
, DEFAULT_GLOBAL_APPS_UNIX_SOCK
);
747 old_umask
= umask(0);
749 snprintf(local_apps_wait_shm_path
, PATH_MAX
,
750 DEFAULT_HOME_APPS_WAIT_SHM_PATH
, getuid());
751 wait_shm_fd
= get_wait_shm(local_apps_wait_shm_path
,
752 sysconf(_SC_PAGE_SIZE
), 0);
753 if (wait_shm_fd
< 0) {
754 perror("local wait shm error");
757 home_dir
= (const char *) getenv("HOME");
759 perror("getenv error");
762 snprintf(apps_sock_path
, PATH_MAX
,
763 DEFAULT_HOME_APPS_UNIX_SOCK
, home_dir
);
766 ret
= ustcomm_create_unix_sock(apps_sock_path
);
768 perror("create error");
774 /* File permission MUST be 666 */
775 ret
= chmod(apps_sock_path
,
776 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
778 printf("Set file permissions failed: %s\n", apps_sock_path
);
784 ret
= ustcomm_listen_unix_sock(apps_socket
);
786 perror("listen error");
790 /* wake up futexes */
791 ret
= update_futex(wait_shm_fd
, 1);
793 fprintf(stderr
, "Error wakeup futex\n");
807 char name
[16]; /* Process name */
814 printf("Accepting application registration\n");
815 sock
= ustcomm_accept_unix_sock(apps_socket
);
817 perror("accept error");
822 * Basic recv here to handle the very simple data
823 * that the libust send to register (reg_msg).
825 len
= ustcomm_recv_unix_sock(sock
, ®_msg
, sizeof(reg_msg
));
826 if (len
< 0 || len
!= sizeof(reg_msg
)) {
827 perror("ustcomm_recv_unix_sock");
830 memcpy(bufname
, reg_msg
.name
, 16);
832 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
833 bufname
, reg_msg
.pid
, reg_msg
.ppid
, reg_msg
.uid
,
834 reg_msg
.gid
, reg_msg
.major
, reg_msg
.minor
);
835 ret
= send_app_msgs(sock
);
837 printf("Error in send_app_msgs.\n");
844 printf("quitting.\n");
845 /* Let applications know we are not responding anymore */
846 ret
= update_futex(wait_shm_fd
, 0);
848 fprintf(stderr
, "Error wakeup futex\n");