Cleanup: apply `include-what-you-use` guideline for `uint*_t`
[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 *
e92f3e28
MD
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.
b0a99af4 10 *
e92f3e28
MD
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.
b0a99af4 15 *
e92f3e28
MD
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.
b0a99af4
MD
19 */
20
21#define _LARGEFILE64_SOURCE
9d335227 22#define _GNU_SOURCE
fb31eb73 23#include <assert.h>
b0a99af4 24#include <errno.h>
fb31eb73
FD
25#include <fcntl.h>
26#include <limits.h>
27#include <signal.h>
28#include <stdint.h>
b0a99af4
MD
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
fb31eb73
FD
32#include <sys/mman.h>
33#include <sys/resource.h>
34#include <sys/socket.h>
b0a99af4 35#include <sys/stat.h>
07dd0d60 36#include <sys/time.h>
fb31eb73
FD
37#include <sys/types.h>
38#include <sys/wait.h>
39#include <unistd.h>
b0a99af4
MD
40#include <urcu/futex.h>
41#include <urcu/uatomic.h>
b0a99af4 42
a3bb4b27 43#include <ust-comm.h>
1a34b35b 44#include <lttng/ust-error.h>
b0a99af4
MD
45#include "../../libringbuffer/backend.h"
46#include "../../libringbuffer/frontend.h"
bdcf8d82 47#include "../../liblttng-ust/compat.h" /* For ENODATA */
b0a99af4
MD
48
49#define MAX_NR_STREAMS 64
50#define MAX_NR_EVENTS 128
51
b0a99af4 52static int session_handle;
61f02aea
MD
53static struct lttng_ust_object_data metadata_stream_data;
54static struct lttng_ust_object_data metadata_data;
55static struct lttng_ust_object_data channel_data;
56static struct lttng_ust_object_data stream_data[MAX_NR_STREAMS];
b0a99af4 57static int event_handle[MAX_NR_EVENTS];
8de38cf7 58static int context_handle;
b0a99af4
MD
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
b0a99af4 71static
61f02aea 72int open_streams(int sock, int channel_handle, struct lttng_ust_object_data *stream_datas,
b0a99af4
MD
73 int nr_check)
74{
75 int ret, k = 0;
76
77 for (;;) {
57773204
MD
78 struct ustcomm_ust_msg lum;
79 struct ustcomm_ust_reply lur;
b0a99af4
MD
80
81 memset(&lum, 0, sizeof(lum));
82 lum.handle = channel_handle;
83 lum.cmd = LTTNG_UST_STREAM;
57773204 84 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
85 if (!ret) {
86 assert(k < nr_check);
87 stream_datas[k].handle = lur.ret_val;
88 printf("received stream handle %u\n",
89 stream_datas[k].handle);
7bc53e94 90 if (lur.ret_code == LTTNG_UST_OK) {
b0a99af4
MD
91 ssize_t len;
92
93 stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
94 /* get shm fd */
57773204 95 len = ustcomm_recv_fd(sock);
b0a99af4
MD
96 if (len < 0)
97 return -EINVAL;
98 stream_datas[k].shm_fd = len;
99 /* get wait fd */
57773204 100 len = ustcomm_recv_fd(sock);
b0a99af4
MD
101 if (len < 0)
102 return -EINVAL;
103 stream_datas[k].wait_fd = len;
104 }
105 k++;
106 }
1a34b35b 107 if (ret == -LTTNG_UST_ERR_NOENT)
b0a99af4
MD
108 break;
109 if (ret)
110 return ret;
111 }
112 return 0;
113}
114
115static
61f02aea 116int close_streams(int sock, struct lttng_ust_object_data *stream_datas, int nr_check)
b0a99af4
MD
117{
118 int ret, k;
119
120 for (k = 0; k < nr_check; k++) {
57773204
MD
121 struct ustcomm_ust_msg lum;
122 struct ustcomm_ust_reply lur;
b0a99af4
MD
123
124 if (!stream_datas[k].handle)
125 continue;
126 memset(&lum, 0, sizeof(lum));
127 lum.handle = stream_datas[k].handle;
128 lum.cmd = LTTNG_UST_RELEASE;
57773204 129 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
130 if (ret) {
131 printf("Error closing stream\n");
132 return ret;
133 }
134 if (stream_datas[k].shm_fd >= 0) {
135 ret = close(stream_datas[k].shm_fd);
136 if (ret) {
137 printf("Error closing stream shm_fd\n");
138 return ret;
139 }
140 }
141 if (stream_datas[k].wait_fd >= 0) {
142 ret = close(stream_datas[k].wait_fd);
143 if (ret) {
144 printf("Error closing stream wait_fd\n");
145 return ret;
146 }
147 }
148 }
149 return 0;
150}
151
152static
38fae1d3 153struct lttng_ust_shm_handle *map_channel(struct lttng_ust_object_data *chan_data,
61f02aea 154 struct lttng_ust_object_data *stream_datas, int nr_check)
b0a99af4 155{
38fae1d3 156 struct lttng_ust_shm_handle *handle;
b0a99af4
MD
157 struct channel *chan;
158 int k, ret;
159
160 /* map metadata channel */
161 handle = channel_handle_create(chan_data->shm_fd,
162 chan_data->wait_fd,
163 chan_data->memory_map_size);
164 if (!handle) {
165 printf("create handle error\n");
166 return NULL;
167 }
168 chan_data->shm_fd = -1;
169 chan_data->wait_fd = -1;
170 chan = shmp(handle, handle->chan);
171
172 for (k = 0; k < nr_check; k++) {
61f02aea 173 struct lttng_ust_object_data *stream_data = &stream_datas[k];
b0a99af4
MD
174
175 if (!stream_data->handle)
176 break;
177 /* map stream */
178 ret = channel_handle_add_stream(handle,
179 stream_data->shm_fd,
180 stream_data->wait_fd,
181 stream_data->memory_map_size);
182 if (ret) {
183 printf("add stream error\n");
184 goto error_destroy;
185 }
186 stream_data->shm_fd = -1;
187 stream_data->wait_fd = -1;
188 }
189 return handle;
190
191error_destroy:
192 channel_destroy(chan, handle, 1);
193 return NULL;
194}
195
196static
38fae1d3 197void unmap_channel(struct lttng_ust_shm_handle *handle)
b0a99af4
MD
198{
199 struct channel *chan;
200
201 chan = shmp(handle, handle->chan);
202 /* unmap channel */
203 channel_destroy(chan, handle, 1);
204}
205
206static
38fae1d3 207int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
b0a99af4
MD
208{
209 struct channel *chan;
4cfec15c 210 struct lttng_ust_lib_ring_buffer *buf;
b0a99af4 211 int outfd, ret;
ef9ff354
MD
212 int *shm_fd, *wait_fd;
213 uint64_t *memory_map_size;
b0a99af4
MD
214
215 chan = shmp(handle, handle->chan);
216
217 /* open stream */
218 buf = channel_get_ring_buffer(&chan->backend.config,
219 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
220 if (!buf)
221 return -ENOENT;
222 ret = lib_ring_buffer_open_read(buf, handle, 1);
223 if (ret) {
224 return -1;
225 }
226
227 /* copy */
5cd19802 228 outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC,
b0a99af4
MD
229 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
230 if (outfd < 0) {
231 perror("open output");
232 return -1;
233 }
234
235 printf("Waiting for buffer data for %s\n", outfile);
236 for (;;) {
237 unsigned long read_size;
238 unsigned long copy_size;
239 char *ptr;
240
241 ret = lib_ring_buffer_get_next_subbuf(buf, handle);
242 printf("get next ret %d\n", ret);
243 if (ret == -ENODATA)
244 break;
245 if (ret == -EAGAIN) {
246 sleep(1);
247 continue;
248 }
249 if (ret) {
250 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret);
251 return -1;
252 }
253 read_size = lib_ring_buffer_get_read_data_size(
254 &chan->backend.config, buf, handle);
255 read_size = PAGE_ALIGN(read_size);
256 ptr = lib_ring_buffer_read_offset_address(
257 &buf->backend, 0, handle);
258 printf("WRITE: copy %lu bytes\n", read_size);
259 copy_size = write(outfd, ptr, read_size);
260 if (copy_size < read_size) {
f97e7ae1 261 printf("write issue: copied %lu, expected %lu\n", copy_size, read_size);
b0a99af4
MD
262 }
263 lib_ring_buffer_put_next_subbuf(buf, handle);
264 }
265
266 ret = close(outfd);
267 if (ret) {
268 perror("close");
269 return -1;
270 }
271
272 /* close stream */
273 lib_ring_buffer_release_read(buf, handle, 1);
274 return 0;
275}
276
277static
278int consume_buffers(const char *outputpath)
279{
280 int k, ret;
281 mode_t old_umask;
282 char pathname[PATH_MAX];
38fae1d3 283 struct lttng_ust_shm_handle *handle;
b0a99af4
MD
284
285 snprintf(pathname, PATH_MAX - 1, "%s", outputpath);
286 old_umask = umask(0);
287 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
288 if (ret && errno != EEXIST) {
289 perror("mkdir");
290 umask(old_umask);
291 return -1;
292 }
293 umask(old_umask);
294
295 /* copy metadata */
296 handle = map_channel(&metadata_data,
297 &metadata_stream_data, 1);
298 if (!handle)
299 return -1;
300 snprintf(pathname, PATH_MAX - 1,
301 "%s/metadata", outputpath);
302 ret = consume_stream(handle, -1, pathname);
303 if (ret && ret != -ENOENT) {
304 printf("Error in consume_stream\n");
305 return ret;
306 }
307 unmap_channel(handle);
308
309 /* copy binary data */
310 handle = map_channel(&channel_data,
311 stream_data, MAX_NR_STREAMS);
312 if (!handle)
313 return -1;
314 for (k = 0; k < MAX_NR_STREAMS; k++) {
315 snprintf(pathname, PATH_MAX - 1,
316 "%s/data_%u", outputpath, k);
317 ret = consume_stream(handle, k, pathname);
318 if (ret && ret != -ENOENT) {
319 printf("Error in consume_stream\n");
320 return ret;
321 }
322 }
323 unmap_channel(handle);
324
325 return 0;
326}
327
57773204 328static
b0a99af4
MD
329int send_app_msgs(int sock, const char *outputpath,
330 unsigned int nr_events, const char **event_names)
331{
57773204
MD
332 struct ustcomm_ust_msg lum;
333 struct ustcomm_ust_reply lur;
b0a99af4
MD
334 int ret, k;
335
336 /* Create session */
337 memset(&lum, 0, sizeof(lum));
338 lum.handle = LTTNG_UST_ROOT_HANDLE;
339 lum.cmd = LTTNG_UST_SESSION;
57773204 340 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
341 if (ret)
342 return ret;
343 session_handle = lur.ret_val;
344 printf("received session handle %u\n", session_handle);
345
346 /* Create metadata channel */
347 memset(&lum, 0, sizeof(lum));
348 lum.handle = session_handle;
349 lum.cmd = LTTNG_UST_METADATA;
350 lum.u.channel.overwrite = 0;
351 lum.u.channel.subbuf_size = 32768;
352 lum.u.channel.num_subbuf = 4;
353 lum.u.channel.switch_timer_interval = 0;
354 lum.u.channel.read_timer_interval = 0;
355 lum.u.channel.output = LTTNG_UST_MMAP;
57773204 356 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
357 if (ret)
358 return ret;
359 metadata_data.handle = lur.ret_val;
360 printf("received metadata handle %u\n", metadata_data.handle);
7bc53e94 361 if (lur.ret_code == LTTNG_UST_OK) {
b0a99af4
MD
362 ssize_t len;
363
364 metadata_data.memory_map_size = lur.u.channel.memory_map_size;
365 /* get shm fd */
57773204 366 len = ustcomm_recv_fd(sock);
b0a99af4
MD
367 if (len < 0)
368 return -EINVAL;
369 metadata_data.shm_fd = len;
370 /* get wait fd */
57773204 371 len = ustcomm_recv_fd(sock);
b0a99af4
MD
372 if (len < 0)
373 return -EINVAL;
374 metadata_data.wait_fd = len;
375 }
376
377 ret = open_streams(sock, metadata_data.handle,
378 &metadata_stream_data, 1);
379 if (ret) {
380 printf("Error in open_streams\n");
381 return ret;
382 }
383
384 /* Create data channel */
385 memset(&lum, 0, sizeof(lum));
386 lum.handle = session_handle;
387 lum.cmd = LTTNG_UST_CHANNEL;
388 //lum.u.channel.overwrite = 0;
389 lum.u.channel.overwrite = 1;
390 lum.u.channel.subbuf_size = 32768;
391 lum.u.channel.num_subbuf = 8;
392 //lum.u.channel.num_subbuf = 4;
393 //lum.u.channel.num_subbuf = 2;
394 lum.u.channel.switch_timer_interval = 0;
395 lum.u.channel.read_timer_interval = 0;
396 lum.u.channel.output = LTTNG_UST_MMAP;
57773204 397 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
398 if (ret)
399 return ret;
400 channel_data.handle = lur.ret_val;
401 printf("received channel handle %u\n", channel_data.handle);
7bc53e94 402 if (lur.ret_code == LTTNG_UST_OK) {
b0a99af4
MD
403 ssize_t len;
404
405 channel_data.memory_map_size = lur.u.channel.memory_map_size;
406 /* get shm fd */
57773204 407 len = ustcomm_recv_fd(sock);
b0a99af4
MD
408 if (len < 0)
409 return -EINVAL;
410 channel_data.shm_fd = len;
411 /* get wait fd */
57773204 412 len = ustcomm_recv_fd(sock);
b0a99af4
MD
413 if (len < 0)
414 return -EINVAL;
415 channel_data.wait_fd = len;
416 }
417
418 /* Create events */
419 for (k = 0; k < nr_events; k++) {
420 memset(&lum, 0, sizeof(lum));
421 lum.handle = channel_data.handle;
422 lum.cmd = LTTNG_UST_EVENT;
423 strncpy(lum.u.event.name, event_names[k],
424 LTTNG_UST_SYM_NAME_LEN);
425 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
57773204 426 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
427 if (ret)
428 return ret;
429 event_handle[k] = lur.ret_val;
430 printf("received event handle %u\n", event_handle[k]);
431 }
432
3b402b40 433 /* Attach vtid context */
8de38cf7
MD
434 memset(&lum, 0, sizeof(lum));
435 lum.handle = channel_data.handle;
436 lum.cmd = LTTNG_UST_CONTEXT;
3b402b40
MD
437 lum.u.context.ctx = LTTNG_UST_CONTEXT_VTID;
438 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PTHREAD_ID;
4847e9bb
MD
439 //lum.u.context.ctx = LTTNG_UST_CONTEXT_VPID;
440 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PROCNAME;
57773204 441 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
8de38cf7
MD
442 if (ret)
443 return ret;
444 context_handle = lur.ret_val;
445 printf("received context handle %u\n", context_handle);
446
b0a99af4
MD
447 /* Get references to channel streams */
448 ret = open_streams(sock, channel_data.handle,
449 stream_data, MAX_NR_STREAMS);
450 if (ret) {
451 printf("Error in open_streams\n");
452 return ret;
453 }
454
455 memset(&lum, 0, sizeof(lum));
456 lum.handle = session_handle;
457 lum.cmd = LTTNG_UST_SESSION_START;
57773204 458 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
459 if (ret)
460 return ret;
461 printf("Session handle %u started.\n", session_handle);
462
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;
57773204 467 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
468 if (ret)
469 return ret;
470 printf("Registration done acknowledged.\n");
471
472 sleep(4);
473
474 ret = consume_buffers(outputpath);
475 if (ret) {
476 printf("Error in consume_buffers\n");
477 return ret;
478 }
479
480 /* Release data channel */
481 /* Release streams */
482 ret = close_streams(sock, stream_data,
483 MAX_NR_STREAMS);
484 if (ret)
485 return ret;
486
8de38cf7
MD
487 /* Release context */
488 memset(&lum, 0, sizeof(lum));
489 lum.handle = context_handle;
490 lum.cmd = LTTNG_UST_RELEASE;
57773204 491 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
8de38cf7
MD
492 if (ret)
493 return ret;
494
b0a99af4
MD
495 /* Release events */
496 for (k = 0; k < nr_events; k++) {
497 memset(&lum, 0, sizeof(lum));
498 lum.handle = event_handle[k];
499 lum.cmd = LTTNG_UST_RELEASE;
57773204 500 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
501 if (ret)
502 return ret;
503 }
504 memset(&lum, 0, sizeof(lum));
505 lum.handle = channel_data.handle;
506 lum.cmd = LTTNG_UST_RELEASE;
57773204 507 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
508 if (ret)
509 return ret;
510 if (channel_data.shm_fd >= 0) {
511 ret = close(channel_data.shm_fd);
512 if (ret)
513 return ret;
514 }
515 if (channel_data.wait_fd >= 0) {
516 ret = close(channel_data.wait_fd);
517 if (ret)
518 return ret;
519 }
520
521 /* Release metadata channel */
522 ret = close_streams(sock, &metadata_stream_data, 1);
523 if (ret)
524 return ret;
525
526 memset(&lum, 0, sizeof(lum));
527 lum.handle = metadata_data.handle;
528 lum.cmd = LTTNG_UST_RELEASE;
57773204 529 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
530 if (ret)
531 return ret;
532 if (metadata_data.shm_fd >= 0) {
533 ret = close(metadata_data.shm_fd);
534 if (ret)
535 return ret;
536 }
537 if (metadata_data.wait_fd >= 0) {
538 ret = close(metadata_data.wait_fd);
539 if (ret)
540 return ret;
541 }
542
543 /* Release session */
544 memset(&lum, 0, sizeof(lum));
545 lum.handle = session_handle;
546 lum.cmd = LTTNG_UST_RELEASE;
57773204 547 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
548 if (ret)
549 return ret;
550
551 return 0;
552}
553
554/*
555 * Using fork to set umask in the child process (not multi-thread safe). We
556 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
557 * the shm and does not let everybody modify it, to ensure safety against
558 * shm_unlink) by simply letting the mmap fail and retrying after a few
559 * seconds. For global shm, everybody has rw access to it until the sessiond
560 * starts.
561 */
562static int get_wait_shm(char *shm_path, size_t mmap_size, int global)
563{
564 int wait_shm_fd, ret;
565 mode_t mode;
566
567 /* Default permissions */
568 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
569
570 /* Change owner of the shm path */
571 if (global) {
572 ret = chown(shm_path, 0, 0);
573 if (ret < 0) {
574 if (errno != ENOENT) {
575 perror("chown wait shm");
576 goto error;
577 }
578 }
579
580 /*
581 * If global session daemon, any application can register so the shm
582 * needs to be set in read-only mode for others.
583 */
584 mode |= S_IROTH;
585 } else {
586 ret = chown(shm_path, getuid(), getgid());
587 if (ret < 0) {
588 if (errno != ENOENT) {
589 perror("chown wait shm");
590 goto error;
591 }
592 }
593 }
594
595 /*
596 * Set permissions to the shm even if we did not create the shm.
597 */
598 ret = chmod(shm_path, mode);
599 if (ret < 0) {
600 if (errno != ENOENT) {
601 perror("chmod wait shm");
602 goto error;
603 }
604 }
605
606 /*
607 * We're alone in a child process, so we can modify the process-wide
608 * umask.
609 */
610 umask(~mode);
611
612 /*
613 * Try creating shm (or get rw access). We don't do an exclusive open,
614 * because we allow other processes to create+ftruncate it concurrently.
615 */
616 wait_shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, mode);
617 if (wait_shm_fd < 0) {
618 perror("shm_open wait shm");
619 goto error;
620 }
621
622 ret = ftruncate(wait_shm_fd, mmap_size);
623 if (ret < 0) {
624 perror("ftruncate wait shm");
625 exit(EXIT_FAILURE);
626 }
627
628 ret = fchmod(wait_shm_fd, mode);
629 if (ret < 0) {
630 perror("fchmod");
631 exit(EXIT_FAILURE);
632 }
633
634 printf("Got the wait shm fd %d\n", wait_shm_fd);
635
636 return wait_shm_fd;
637
638error:
639 printf("Failing to get the wait shm fd\n");
640
641 return -1;
642}
643
644int update_futex(int fd, int active)
645{
172d6b68 646 long page_size;
b0a99af4
MD
647 char *wait_shm_mmap;
648 int ret;
649
172d6b68 650 page_size = sysconf(_SC_PAGE_SIZE);
2657d1ba
MD
651 if (page_size <= 0) {
652 if (!page_size) {
653 errno = EINVAL;
654 }
655 perror("Error in sysconf(_SC_PAGE_SIZE)");
172d6b68
MD
656 goto error;
657 }
658 wait_shm_mmap = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
b0a99af4
MD
659 MAP_SHARED, fd, 0);
660 if (wait_shm_mmap == MAP_FAILED) {
661 perror("mmap");
662 goto error;
663 }
664
665 if (active) {
666 uatomic_set((int32_t *) wait_shm_mmap, 1);
ee7fcec8
MD
667 if (futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
668 INT_MAX, NULL, NULL, 0) < 0) {
669 perror("futex_async");
670 goto error;
671 }
b0a99af4
MD
672 } else {
673 uatomic_set((int32_t *) wait_shm_mmap, 0);
674 }
172d6b68 675 ret = munmap(wait_shm_mmap, page_size);
b0a99af4
MD
676 if (ret) {
677 perror("Error unmapping wait shm");
678 goto error;
679 }
680 return 0;
681error:
682 return -1;
683}
684
685/*
686 * Set open files limit to unlimited. This daemon can open a large number of
687 * file descriptors in order to consumer multiple kernel traces.
688 */
689static void set_ulimit(void)
690{
691 int ret;
692 struct rlimit lim;
693
694 /*
695 * If not root, we cannot increase our max open files. But our
696 * scope is then limited to processes from a single user.
697 */
698 if (getuid() != 0)
699 return;
700 /* The kernel does not allowed an infinite limit for open files */
701 lim.rlim_cur = 65535;
702 lim.rlim_max = 65535;
703
704 ret = setrlimit(RLIMIT_NOFILE, &lim);
705 if (ret < 0) {
706 perror("failed to set open files limit");
707 }
708}
709
710/*
711 * Usage:
712 * ./ust-basic-tracing outputpath event_name1 event_name2 ....
713 */
714int main(int argc, const char **argv)
715{
716 const char *home_dir;
3d39c98c
CB
717 char home_rundir[PATH_MAX];
718 char *cmd = NULL;
b0a99af4
MD
719 int ret, wait_shm_fd;
720 struct sigaction act;
fb50c39d 721 mode_t old_umask = 0;
b0a99af4
MD
722 const char *outputpath;
723 const char **event_names;
724 unsigned int nr_events;
2657d1ba 725 long page_size;
b0a99af4
MD
726
727 if (argc < 2) {
728 printf("Usage:\n");
729 printf("%s outputpath event_name1 event_name2 ...\n",
730 argv[0]);
731 exit(-1);
732 }
733 outputpath = argv[1];
734 event_names = &argv[2];
735 nr_events = argc - 2;
736
737 set_ulimit();
738
739 /* Ignore sigpipe */
740 memset(&act, 0, sizeof(act));
741 ret = sigemptyset(&act.sa_mask);
742 if (ret == -1) {
743 perror("sigemptyset");
744 return -1;
745 }
746
747 act.sa_handler = SIG_IGN;
748 ret = sigaction(SIGPIPE, &act, NULL);
749 if (ret == -1) {
750 perror("sigaction");
751 return -1;
752 }
753
754 /* Handle SIGTERM */
755 act.sa_handler = handle_signals;
756 ret = sigaction(SIGTERM, &act, NULL);
757 if (ret == -1) {
758 perror("sigaction");
759 return -1;
760 }
761 /* Handle SIGINT */
762 ret = sigaction(SIGINT, &act, NULL);
763 if (ret == -1) {
764 perror("sigaction");
765 return -1;
766 }
767
2657d1ba
MD
768 page_size = sysconf(_SC_PAGE_SIZE);
769 if (page_size <= 0) {
770 if (!page_size) {
771 errno = EINVAL;
772 }
773 perror("Error in sysconf(_SC_PAGE_SIZE)");
774 return -1;
775 }
776
b0a99af4
MD
777 if (geteuid() == 0) {
778 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
779 if (ret && errno != EEXIST) {
780 perror("mkdir");
781 return -1;
782 }
783 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
2657d1ba 784 page_size, 1);
b0a99af4
MD
785 if (wait_shm_fd < 0) {
786 perror("global wait shm error");
787 return -1;
788 }
789 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
790 old_umask = umask(0);
791 } else {
3d39c98c
CB
792 home_dir = (const char *) getenv("HOME");
793 if (!home_dir) {
794 perror("getenv error");
795 return -ENOENT;
796 }
797
798 snprintf(home_rundir, PATH_MAX,
799 LTTNG_HOME_RUNDIR, home_dir);
800
801 ret = mkdir(home_rundir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
802 if (ret && errno != EEXIST) {
803 perror("mkdir");
804 return -1;
805 }
806
b0a99af4
MD
807 snprintf(local_apps_wait_shm_path, PATH_MAX,
808 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
809 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
2657d1ba 810 page_size, 0);
b0a99af4
MD
811 if (wait_shm_fd < 0) {
812 perror("local wait shm error");
813 return -1;
814 }
b0a99af4
MD
815 snprintf(apps_sock_path, PATH_MAX,
816 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
817 }
818
57773204 819 ret = ustcomm_create_unix_sock(apps_sock_path);
b0a99af4
MD
820 if (ret < 0) {
821 perror("create error");
822 return ret;
823 }
824 apps_socket = ret;
825
826 if (getuid() == 0) {
827 /* File permission MUST be 666 */
828 ret = chmod(apps_sock_path,
829 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
830 if (ret < 0) {
831 printf("Set file permissions failed: %s\n", apps_sock_path);
832 perror("chmod");
833 goto end;
834 }
835 umask(old_umask);
836 }
57773204 837 ret = ustcomm_listen_unix_sock(apps_socket);
b0a99af4
MD
838 if (ret < 0) {
839 perror("listen error");
840 return ret;
841 }
842
843 /* wake up futexes */
844 ret = update_futex(wait_shm_fd, 1);
845 if (ret) {
846 fprintf(stderr, "Error wakeup futex\n");
847 return -1;
848 }
849
850 for (;;) {
851 int sock;
852 ssize_t len;
853 struct {
854 uint32_t major;
855 uint32_t minor;
856 pid_t pid;
857 pid_t ppid;
858 uid_t uid;
859 gid_t gid;
1a34b35b 860 uint32_t bits_per_long;
b0a99af4
MD
861 char name[16]; /* Process name */
862 } reg_msg;
863 char bufname[17];
864
865 if (quit_program)
866 break;
867
868 printf("Accepting application registration\n");
57773204 869 sock = ustcomm_accept_unix_sock(apps_socket);
b0a99af4
MD
870 if (sock < 0) {
871 perror("accept error");
872 goto end;
873 }
874
875 /*
876 * Basic recv here to handle the very simple data
877 * that the libust send to register (reg_msg).
878 */
57773204 879 len = ustcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
b0a99af4 880 if (len < 0 || len != sizeof(reg_msg)) {
57773204 881 perror("ustcomm_recv_unix_sock");
b0a99af4
MD
882 continue;
883 }
884 memcpy(bufname, reg_msg.name, 16);
885 bufname[16] = '\0';
886 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
887 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
888 reg_msg.gid, reg_msg.major, reg_msg.minor);
889 ret = send_app_msgs(sock, outputpath, nr_events, event_names);
890 if (ret) {
891 printf("Error in send_app_msgs.\n");
892 sleep(1);
893 }
894 close(sock);
895 }
896
897end:
898 printf("quitting.\n");
899 /* Let applications know we are not responding anymore */
900 ret = update_futex(wait_shm_fd, 0);
901 if (ret) {
902 fprintf(stderr, "Error wakeup futex\n");
903 return -1;
904 }
905
3d39c98c
CB
906 if (geteuid()) {
907 printf("Removing %s directory\n", home_rundir);
908 ret = asprintf(&cmd, "rm -rf %s", home_rundir);
909 if (ret < 0) {
910 printf("asprintf failed. Something is really wrong!\n");
911 return -1;
912 }
913
914 /* Remove lttng run directory */
915 ret = system(cmd);
916 if (ret < 0) {
917 printf("Unable to clean %s\n", home_rundir);
918 return -1;
919 }
920 }
921
922
b0a99af4
MD
923 return 0;
924}
This page took 0.067781 seconds and 4 git commands to generate.