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