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