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