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