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