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