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