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