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