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