e704af1f9e346768f310bcbc9479fd80f2a56c5a
[lttng-ust.git] / tests / ust-basic-tracing / ust-basic-tracing.c
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
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.
10 *
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.
15 *
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.
19 */
20
21 #define _LARGEFILE64_SOURCE
22 #define _GNU_SOURCE
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 <sys/time.h>
33 #include <sys/resource.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
42 #include <ust-comm.h>
43 #include "../../libringbuffer/backend.h"
44 #include "../../libringbuffer/frontend.h"
45
46 #define MAX_NR_STREAMS 64
47 #define MAX_NR_EVENTS 128
48
49 static int session_handle;
50 static struct lttng_ust_object_data metadata_stream_data;
51 static struct lttng_ust_object_data metadata_data;
52 static struct lttng_ust_object_data channel_data;
53 static struct lttng_ust_object_data stream_data[MAX_NR_STREAMS];
54 static int event_handle[MAX_NR_EVENTS];
55 static int context_handle;
56
57 static int apps_socket = -1;
58 static char apps_sock_path[PATH_MAX];
59 static char local_apps_wait_shm_path[PATH_MAX];
60
61 static volatile int quit_program;
62
63 static void handle_signals(int signo)
64 {
65 quit_program = 1;
66 }
67
68 static
69 int open_streams(int sock, int channel_handle, struct lttng_ust_object_data *stream_datas,
70 int nr_check)
71 {
72 int ret, k = 0;
73
74 for (;;) {
75 struct ustcomm_ust_msg lum;
76 struct ustcomm_ust_reply lur;
77
78 memset(&lum, 0, sizeof(lum));
79 lum.handle = channel_handle;
80 lum.cmd = LTTNG_UST_STREAM;
81 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
82 if (!ret) {
83 assert(k < nr_check);
84 stream_datas[k].handle = lur.ret_val;
85 printf("received stream handle %u\n",
86 stream_datas[k].handle);
87 if (lur.ret_code == USTCOMM_OK) {
88 ssize_t len;
89
90 stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
91 /* get shm fd */
92 len = ustcomm_recv_fd(sock);
93 if (len < 0)
94 return -EINVAL;
95 stream_datas[k].shm_fd = len;
96 /* get wait fd */
97 len = ustcomm_recv_fd(sock);
98 if (len < 0)
99 return -EINVAL;
100 stream_datas[k].wait_fd = len;
101 }
102 k++;
103 }
104 if (ret == -ENOENT)
105 break;
106 if (ret)
107 return ret;
108 }
109 return 0;
110 }
111
112 static
113 int close_streams(int sock, struct lttng_ust_object_data *stream_datas, int nr_check)
114 {
115 int ret, k;
116
117 for (k = 0; k < nr_check; k++) {
118 struct ustcomm_ust_msg lum;
119 struct ustcomm_ust_reply lur;
120
121 if (!stream_datas[k].handle)
122 continue;
123 memset(&lum, 0, sizeof(lum));
124 lum.handle = stream_datas[k].handle;
125 lum.cmd = LTTNG_UST_RELEASE;
126 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
127 if (ret) {
128 printf("Error closing stream\n");
129 return ret;
130 }
131 if (stream_datas[k].shm_fd >= 0) {
132 ret = close(stream_datas[k].shm_fd);
133 if (ret) {
134 printf("Error closing stream shm_fd\n");
135 return ret;
136 }
137 }
138 if (stream_datas[k].wait_fd >= 0) {
139 ret = close(stream_datas[k].wait_fd);
140 if (ret) {
141 printf("Error closing stream wait_fd\n");
142 return ret;
143 }
144 }
145 }
146 return 0;
147 }
148
149 static
150 struct lttng_ust_shm_handle *map_channel(struct lttng_ust_object_data *chan_data,
151 struct lttng_ust_object_data *stream_datas, int nr_check)
152 {
153 struct lttng_ust_shm_handle *handle;
154 struct channel *chan;
155 int k, ret;
156
157 /* map metadata channel */
158 handle = channel_handle_create(chan_data->shm_fd,
159 chan_data->wait_fd,
160 chan_data->memory_map_size);
161 if (!handle) {
162 printf("create handle error\n");
163 return NULL;
164 }
165 chan_data->shm_fd = -1;
166 chan_data->wait_fd = -1;
167 chan = shmp(handle, handle->chan);
168
169 for (k = 0; k < nr_check; k++) {
170 struct lttng_ust_object_data *stream_data = &stream_datas[k];
171
172 if (!stream_data->handle)
173 break;
174 /* map stream */
175 ret = channel_handle_add_stream(handle,
176 stream_data->shm_fd,
177 stream_data->wait_fd,
178 stream_data->memory_map_size);
179 if (ret) {
180 printf("add stream error\n");
181 goto error_destroy;
182 }
183 stream_data->shm_fd = -1;
184 stream_data->wait_fd = -1;
185 }
186 return handle;
187
188 error_destroy:
189 channel_destroy(chan, handle, 1);
190 return NULL;
191 }
192
193 static
194 void unmap_channel(struct lttng_ust_shm_handle *handle)
195 {
196 struct channel *chan;
197
198 chan = shmp(handle, handle->chan);
199 /* unmap channel */
200 channel_destroy(chan, handle, 1);
201 }
202
203 static
204 int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
205 {
206 struct channel *chan;
207 struct lttng_ust_lib_ring_buffer *buf;
208 int outfd, ret;
209 int *shm_fd, *wait_fd;
210 uint64_t *memory_map_size;
211
212 chan = shmp(handle, handle->chan);
213
214 /* open stream */
215 buf = channel_get_ring_buffer(&chan->backend.config,
216 chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
217 if (!buf)
218 return -ENOENT;
219 ret = lib_ring_buffer_open_read(buf, handle, 1);
220 if (ret) {
221 return -1;
222 }
223
224 /* copy */
225 outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC,
226 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
227 if (outfd < 0) {
228 perror("open output");
229 return -1;
230 }
231
232 printf("Waiting for buffer data for %s\n", outfile);
233 for (;;) {
234 unsigned long read_size;
235 unsigned long copy_size;
236 char *ptr;
237
238 ret = lib_ring_buffer_get_next_subbuf(buf, handle);
239 printf("get next ret %d\n", ret);
240 if (ret == -ENODATA)
241 break;
242 if (ret == -EAGAIN) {
243 sleep(1);
244 continue;
245 }
246 if (ret) {
247 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret);
248 return -1;
249 }
250 read_size = lib_ring_buffer_get_read_data_size(
251 &chan->backend.config, buf, handle);
252 read_size = PAGE_ALIGN(read_size);
253 ptr = lib_ring_buffer_read_offset_address(
254 &buf->backend, 0, handle);
255 printf("WRITE: copy %lu bytes\n", read_size);
256 copy_size = write(outfd, ptr, read_size);
257 if (copy_size < read_size) {
258 printf("write issue: copied %lu, expected %lu\n", copy_size, read_size);
259 }
260 lib_ring_buffer_put_next_subbuf(buf, handle);
261 }
262
263 ret = close(outfd);
264 if (ret) {
265 perror("close");
266 return -1;
267 }
268
269 /* close stream */
270 lib_ring_buffer_release_read(buf, handle, 1);
271 return 0;
272 }
273
274 static
275 int consume_buffers(const char *outputpath)
276 {
277 int k, ret;
278 mode_t old_umask;
279 char pathname[PATH_MAX];
280 struct lttng_ust_shm_handle *handle;
281
282 snprintf(pathname, PATH_MAX - 1, "%s", outputpath);
283 old_umask = umask(0);
284 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
285 if (ret && errno != EEXIST) {
286 perror("mkdir");
287 umask(old_umask);
288 return -1;
289 }
290 umask(old_umask);
291
292 /* copy metadata */
293 handle = map_channel(&metadata_data,
294 &metadata_stream_data, 1);
295 if (!handle)
296 return -1;
297 snprintf(pathname, PATH_MAX - 1,
298 "%s/metadata", outputpath);
299 ret = consume_stream(handle, -1, pathname);
300 if (ret && ret != -ENOENT) {
301 printf("Error in consume_stream\n");
302 return ret;
303 }
304 unmap_channel(handle);
305
306 /* copy binary data */
307 handle = map_channel(&channel_data,
308 stream_data, MAX_NR_STREAMS);
309 if (!handle)
310 return -1;
311 for (k = 0; k < MAX_NR_STREAMS; k++) {
312 snprintf(pathname, PATH_MAX - 1,
313 "%s/data_%u", outputpath, k);
314 ret = consume_stream(handle, k, pathname);
315 if (ret && ret != -ENOENT) {
316 printf("Error in consume_stream\n");
317 return ret;
318 }
319 }
320 unmap_channel(handle);
321
322 return 0;
323 }
324
325 static
326 int send_app_msgs(int sock, const char *outputpath,
327 unsigned int nr_events, const char **event_names)
328 {
329 struct ustcomm_ust_msg lum;
330 struct ustcomm_ust_reply lur;
331 int ret, k;
332
333 /* Create session */
334 memset(&lum, 0, sizeof(lum));
335 lum.handle = LTTNG_UST_ROOT_HANDLE;
336 lum.cmd = LTTNG_UST_SESSION;
337 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
338 if (ret)
339 return ret;
340 session_handle = lur.ret_val;
341 printf("received session handle %u\n", session_handle);
342
343 /* Create metadata channel */
344 memset(&lum, 0, sizeof(lum));
345 lum.handle = session_handle;
346 lum.cmd = LTTNG_UST_METADATA;
347 lum.u.channel.overwrite = 0;
348 lum.u.channel.subbuf_size = 32768;
349 lum.u.channel.num_subbuf = 4;
350 lum.u.channel.switch_timer_interval = 0;
351 lum.u.channel.read_timer_interval = 0;
352 lum.u.channel.output = LTTNG_UST_MMAP;
353 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
354 if (ret)
355 return ret;
356 metadata_data.handle = lur.ret_val;
357 printf("received metadata handle %u\n", metadata_data.handle);
358 if (lur.ret_code == USTCOMM_OK) {
359 ssize_t len;
360
361 metadata_data.memory_map_size = lur.u.channel.memory_map_size;
362 /* get shm fd */
363 len = ustcomm_recv_fd(sock);
364 if (len < 0)
365 return -EINVAL;
366 metadata_data.shm_fd = len;
367 /* get wait fd */
368 len = ustcomm_recv_fd(sock);
369 if (len < 0)
370 return -EINVAL;
371 metadata_data.wait_fd = len;
372 }
373
374 ret = open_streams(sock, metadata_data.handle,
375 &metadata_stream_data, 1);
376 if (ret) {
377 printf("Error in open_streams\n");
378 return ret;
379 }
380
381 /* Create data channel */
382 memset(&lum, 0, sizeof(lum));
383 lum.handle = session_handle;
384 lum.cmd = LTTNG_UST_CHANNEL;
385 //lum.u.channel.overwrite = 0;
386 lum.u.channel.overwrite = 1;
387 lum.u.channel.subbuf_size = 32768;
388 lum.u.channel.num_subbuf = 8;
389 //lum.u.channel.num_subbuf = 4;
390 //lum.u.channel.num_subbuf = 2;
391 lum.u.channel.switch_timer_interval = 0;
392 lum.u.channel.read_timer_interval = 0;
393 lum.u.channel.output = LTTNG_UST_MMAP;
394 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
395 if (ret)
396 return ret;
397 channel_data.handle = lur.ret_val;
398 printf("received channel handle %u\n", channel_data.handle);
399 if (lur.ret_code == USTCOMM_OK) {
400 ssize_t len;
401
402 channel_data.memory_map_size = lur.u.channel.memory_map_size;
403 /* get shm fd */
404 len = ustcomm_recv_fd(sock);
405 if (len < 0)
406 return -EINVAL;
407 channel_data.shm_fd = len;
408 /* get wait fd */
409 len = ustcomm_recv_fd(sock);
410 if (len < 0)
411 return -EINVAL;
412 channel_data.wait_fd = len;
413 }
414
415 /* Create events */
416 for (k = 0; k < nr_events; k++) {
417 memset(&lum, 0, sizeof(lum));
418 lum.handle = channel_data.handle;
419 lum.cmd = LTTNG_UST_EVENT;
420 strncpy(lum.u.event.name, event_names[k],
421 LTTNG_UST_SYM_NAME_LEN);
422 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
423 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
424 if (ret)
425 return ret;
426 event_handle[k] = lur.ret_val;
427 printf("received event handle %u\n", event_handle[k]);
428 }
429
430 /* Attach vtid context */
431 memset(&lum, 0, sizeof(lum));
432 lum.handle = channel_data.handle;
433 lum.cmd = LTTNG_UST_CONTEXT;
434 lum.u.context.ctx = LTTNG_UST_CONTEXT_VTID;
435 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PTHREAD_ID;
436 //lum.u.context.ctx = LTTNG_UST_CONTEXT_VPID;
437 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PROCNAME;
438 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
439 if (ret)
440 return ret;
441 context_handle = lur.ret_val;
442 printf("received context handle %u\n", context_handle);
443
444 /* Get references to channel streams */
445 ret = open_streams(sock, channel_data.handle,
446 stream_data, MAX_NR_STREAMS);
447 if (ret) {
448 printf("Error in open_streams\n");
449 return ret;
450 }
451
452 memset(&lum, 0, sizeof(lum));
453 lum.handle = session_handle;
454 lum.cmd = LTTNG_UST_SESSION_START;
455 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
456 if (ret)
457 return ret;
458 printf("Session handle %u started.\n", session_handle);
459
460 /* Tell application registration is done */
461 memset(&lum, 0, sizeof(lum));
462 lum.handle = LTTNG_UST_ROOT_HANDLE;
463 lum.cmd = LTTNG_UST_REGISTER_DONE;
464 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
465 if (ret)
466 return ret;
467 printf("Registration done acknowledged.\n");
468
469 sleep(4);
470
471 ret = consume_buffers(outputpath);
472 if (ret) {
473 printf("Error in consume_buffers\n");
474 return ret;
475 }
476
477 /* Release data channel */
478 /* Release streams */
479 ret = close_streams(sock, stream_data,
480 MAX_NR_STREAMS);
481 if (ret)
482 return ret;
483
484 /* Release context */
485 memset(&lum, 0, sizeof(lum));
486 lum.handle = context_handle;
487 lum.cmd = LTTNG_UST_RELEASE;
488 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
489 if (ret)
490 return ret;
491
492 /* Release events */
493 for (k = 0; k < nr_events; k++) {
494 memset(&lum, 0, sizeof(lum));
495 lum.handle = event_handle[k];
496 lum.cmd = LTTNG_UST_RELEASE;
497 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
498 if (ret)
499 return ret;
500 }
501 memset(&lum, 0, sizeof(lum));
502 lum.handle = channel_data.handle;
503 lum.cmd = LTTNG_UST_RELEASE;
504 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
505 if (ret)
506 return ret;
507 if (channel_data.shm_fd >= 0) {
508 ret = close(channel_data.shm_fd);
509 if (ret)
510 return ret;
511 }
512 if (channel_data.wait_fd >= 0) {
513 ret = close(channel_data.wait_fd);
514 if (ret)
515 return ret;
516 }
517
518 /* Release metadata channel */
519 ret = close_streams(sock, &metadata_stream_data, 1);
520 if (ret)
521 return ret;
522
523 memset(&lum, 0, sizeof(lum));
524 lum.handle = metadata_data.handle;
525 lum.cmd = LTTNG_UST_RELEASE;
526 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
527 if (ret)
528 return ret;
529 if (metadata_data.shm_fd >= 0) {
530 ret = close(metadata_data.shm_fd);
531 if (ret)
532 return ret;
533 }
534 if (metadata_data.wait_fd >= 0) {
535 ret = close(metadata_data.wait_fd);
536 if (ret)
537 return ret;
538 }
539
540 /* Release session */
541 memset(&lum, 0, sizeof(lum));
542 lum.handle = session_handle;
543 lum.cmd = LTTNG_UST_RELEASE;
544 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
545 if (ret)
546 return ret;
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 */
559 static 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
635 error:
636 printf("Failing to get the wait shm fd\n");
637
638 return -1;
639 }
640
641 int 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;
667 error:
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 */
675 static 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
696 /*
697 * Usage:
698 * ./ust-basic-tracing outputpath event_name1 event_name2 ....
699 */
700 int main(int argc, const char **argv)
701 {
702 const char *home_dir;
703 int ret, wait_shm_fd;
704 struct sigaction act;
705 mode_t old_umask = 0;
706 const char *outputpath;
707 const char **event_names;
708 unsigned int nr_events;
709
710 if (argc < 2) {
711 printf("Usage:\n");
712 printf("%s outputpath event_name1 event_name2 ...\n",
713 argv[0]);
714 exit(-1);
715 }
716 outputpath = argv[1];
717 event_names = &argv[2];
718 nr_events = argc - 2;
719
720 set_ulimit();
721
722 /* Ignore sigpipe */
723 memset(&act, 0, sizeof(act));
724 ret = sigemptyset(&act.sa_mask);
725 if (ret == -1) {
726 perror("sigemptyset");
727 return -1;
728 }
729
730 act.sa_handler = SIG_IGN;
731 ret = sigaction(SIGPIPE, &act, NULL);
732 if (ret == -1) {
733 perror("sigaction");
734 return -1;
735 }
736
737 /* Handle SIGTERM */
738 act.sa_handler = handle_signals;
739 ret = sigaction(SIGTERM, &act, NULL);
740 if (ret == -1) {
741 perror("sigaction");
742 return -1;
743 }
744 /* Handle SIGINT */
745 ret = sigaction(SIGINT, &act, NULL);
746 if (ret == -1) {
747 perror("sigaction");
748 return -1;
749 }
750
751 if (geteuid() == 0) {
752 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
753 if (ret && errno != EEXIST) {
754 perror("mkdir");
755 return -1;
756 }
757 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
758 sysconf(_SC_PAGE_SIZE), 1);
759 if (wait_shm_fd < 0) {
760 perror("global wait shm error");
761 return -1;
762 }
763 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
764 old_umask = umask(0);
765 } else {
766 snprintf(local_apps_wait_shm_path, PATH_MAX,
767 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
768 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
769 sysconf(_SC_PAGE_SIZE), 0);
770 if (wait_shm_fd < 0) {
771 perror("local wait shm error");
772 return -1;
773 }
774 home_dir = (const char *) getenv("HOME");
775 if (!home_dir) {
776 perror("getenv error");
777 return -ENOENT;
778 }
779 snprintf(apps_sock_path, PATH_MAX,
780 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
781 }
782
783 ret = ustcomm_create_unix_sock(apps_sock_path);
784 if (ret < 0) {
785 perror("create error");
786 return ret;
787 }
788 apps_socket = ret;
789
790 if (getuid() == 0) {
791 /* File permission MUST be 666 */
792 ret = chmod(apps_sock_path,
793 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
794 if (ret < 0) {
795 printf("Set file permissions failed: %s\n", apps_sock_path);
796 perror("chmod");
797 goto end;
798 }
799 umask(old_umask);
800 }
801 ret = ustcomm_listen_unix_sock(apps_socket);
802 if (ret < 0) {
803 perror("listen error");
804 return ret;
805 }
806
807 /* wake up futexes */
808 ret = update_futex(wait_shm_fd, 1);
809 if (ret) {
810 fprintf(stderr, "Error wakeup futex\n");
811 return -1;
812 }
813
814 for (;;) {
815 int sock;
816 ssize_t len;
817 struct {
818 uint32_t major;
819 uint32_t minor;
820 pid_t pid;
821 pid_t ppid;
822 uid_t uid;
823 gid_t gid;
824 char name[16]; /* Process name */
825 } reg_msg;
826 char bufname[17];
827
828 if (quit_program)
829 break;
830
831 printf("Accepting application registration\n");
832 sock = ustcomm_accept_unix_sock(apps_socket);
833 if (sock < 0) {
834 perror("accept error");
835 goto end;
836 }
837
838 /*
839 * Basic recv here to handle the very simple data
840 * that the libust send to register (reg_msg).
841 */
842 len = ustcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
843 if (len < 0 || len != sizeof(reg_msg)) {
844 perror("ustcomm_recv_unix_sock");
845 continue;
846 }
847 memcpy(bufname, reg_msg.name, 16);
848 bufname[16] = '\0';
849 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
850 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
851 reg_msg.gid, reg_msg.major, reg_msg.minor);
852 ret = send_app_msgs(sock, outputpath, nr_events, event_names);
853 if (ret) {
854 printf("Error in send_app_msgs.\n");
855 sleep(1);
856 }
857 close(sock);
858 }
859
860 end:
861 printf("quitting.\n");
862 /* Let applications know we are not responding anymore */
863 ret = update_futex(wait_shm_fd, 0);
864 if (ret) {
865 fprintf(stderr, "Error wakeup futex\n");
866 return -1;
867 }
868
869 return 0;
870 }
This page took 0.04491 seconds and 3 git commands to generate.