2 * ust-multi-test.c - single-proces, multi-session, multi-channel, multi-event UST tracing
4 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
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.
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
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.
21 #define _LARGEFILE64_SOURCE
29 #include <sys/types.h>
34 #include <urcu/futex.h>
35 #include <urcu/uatomic.h>
37 #include <sys/socket.h>
39 #include "lttng-ust-comm.h"
40 #include <../../libringbuffer/backend.h>
41 #include <../../libringbuffer/frontend.h>
45 #define MAX_NR_STREAMS 64
48 const char *evname
[] = {
49 "ust_tests_hello_tptest",
50 "ust_tests_hello_tptest_sighandler",
51 "ust_tests_hello_dontexist",
58 uint64_t memory_map_size
;
61 static int session_handle
[NR_SESSIONS
];
62 static struct object_data metadata_stream_data
[NR_SESSIONS
];
63 static struct object_data metadata_data
[NR_SESSIONS
];
64 static struct object_data channel_data
[NR_SESSIONS
][NR_CHANNELS
];
65 static struct object_data stream_data
[NR_SESSIONS
][NR_CHANNELS
][MAX_NR_STREAMS
];
66 static int event_handle
[NR_SESSIONS
][NR_CHANNELS
][NR_EVENTS
];
68 static int apps_socket
= -1;
69 static char apps_sock_path
[PATH_MAX
];
70 static char local_apps_wait_shm_path
[PATH_MAX
];
72 static volatile int quit_program
;
74 static void handle_signals(int signo
)
79 static int send_app_msg(int sock
, struct lttcomm_ust_msg
*lum
)
83 len
= lttcomm_send_unix_sock(sock
, lum
, sizeof(*lum
));
86 printf("message successfully sent\n");
89 if (errno
== ECONNRESET
) {
90 printf("remote end closed connection\n");
95 printf("incorrect message size: %zd\n", len
);
101 static int recv_app_reply(int sock
, struct lttcomm_ust_reply
*lur
,
102 uint32_t expected_handle
, uint32_t expected_cmd
)
106 memset(lur
, 0, sizeof(*lur
));
107 len
= lttcomm_recv_unix_sock(sock
, lur
, sizeof(*lur
));
109 case 0: /* orderly shutdown */
110 printf("Application has performed an orderly shutdown\n");
113 printf("result message received\n");
114 if (lur
->handle
!= expected_handle
) {
115 printf("Unexpected result message handle\n");
119 if (lur
->cmd
!= expected_cmd
) {
120 printf("Unexpected result message command\n");
123 if (lur
->ret_code
!= LTTCOMM_OK
) {
124 printf("remote operation failed with code %d.\n",
126 return lur
->ret_code
;
130 if (errno
== ECONNRESET
) {
131 printf("remote end closed connection\n");
136 printf("incorrect message size: %zd\n", len
);
137 return len
> 0 ? -1 : len
;
141 static int send_app_cmd(int sock
,
142 struct lttcomm_ust_msg
*lum
,
143 struct lttcomm_ust_reply
*lur
)
147 ret
= send_app_msg(sock
, lum
);
150 ret
= recv_app_reply(sock
, lur
, lum
->handle
, lum
->cmd
);
158 * Receives a single fd from socket.
160 * Returns the size of received data
162 static int lttcomm_recv_fd(int sock
)
167 struct cmsghdr
*cmsg
;
168 char recv_fd
[CMSG_SPACE(sizeof(int))];
169 struct msghdr msg
= { 0 };
176 /* Prepare to receive the structures */
177 iov
[0].iov_base
= &data_fd
;
178 iov
[0].iov_len
= sizeof(data_fd
);
181 msg
.msg_control
= recv_fd
;
182 msg
.msg_controllen
= sizeof(recv_fd
);
184 printf("Waiting to receive fd\n");
185 if ((ret
= recvmsg(sock
, &msg
, 0)) < 0) {
189 if (ret
!= sizeof(data_fd
)) {
190 printf("Received %d bytes, expected %ld", ret
, sizeof(data_fd
));
193 cmsg
= CMSG_FIRSTHDR(&msg
);
195 printf("Invalid control message header\n");
199 if (cmsg
->cmsg_level
!= SOL_SOCKET
|| cmsg
->cmsg_type
!= SCM_RIGHTS
) {
200 printf("Didn't received any fd\n");
205 for (i
= 0; i
< sizeof(int); i
++)
206 tmp
.vc
[i
] = CMSG_DATA(cmsg
)[i
];
208 printf("received fd %d\n", ret
);
215 int open_streams(int sock
, int channel_handle
, struct object_data
*stream_datas
,
221 struct lttcomm_ust_msg lum
;
222 struct lttcomm_ust_reply lur
;
224 memset(&lum
, 0, sizeof(lum
));
225 lum
.handle
= channel_handle
;
226 lum
.cmd
= LTTNG_UST_STREAM
;
227 ret
= send_app_cmd(sock
, &lum
, &lur
);
229 assert(k
< nr_check
);
230 stream_datas
[k
].handle
= lur
.ret_val
;
231 printf("received stream handle %u\n",
232 stream_datas
[k
].handle
);
233 if (lur
.ret_code
== LTTCOMM_OK
) {
236 stream_datas
[k
].memory_map_size
= lur
.u
.stream
.memory_map_size
;
238 len
= lttcomm_recv_fd(sock
);
241 stream_datas
[k
].shm_fd
= len
;
243 len
= lttcomm_recv_fd(sock
);
246 stream_datas
[k
].wait_fd
= len
;
259 int close_streams(int sock
, struct object_data
*stream_datas
, int nr_check
)
263 for (k
= 0; k
< nr_check
; k
++) {
264 struct lttcomm_ust_msg lum
;
265 struct lttcomm_ust_reply lur
;
267 if (!stream_datas
[k
].handle
)
269 memset(&lum
, 0, sizeof(lum
));
270 lum
.handle
= stream_datas
[k
].handle
;
271 lum
.cmd
= LTTNG_UST_RELEASE
;
272 ret
= send_app_cmd(sock
, &lum
, &lur
);
274 printf("Error closing stream\n");
277 if (stream_datas
[k
].shm_fd
>= 0) {
278 ret
= close(stream_datas
[k
].shm_fd
);
280 printf("Error closing stream shm_fd\n");
284 if (stream_datas
[k
].wait_fd
>= 0) {
285 ret
= close(stream_datas
[k
].wait_fd
);
287 printf("Error closing stream wait_fd\n");
296 struct shm_handle
*map_channel(struct object_data
*chan_data
,
297 struct object_data
*stream_datas
, int nr_check
)
299 struct shm_handle
*handle
;
300 struct channel
*chan
;
303 /* map metadata channel */
304 handle
= channel_handle_create(chan_data
->shm_fd
,
306 chan_data
->memory_map_size
);
308 printf("create handle error\n");
311 chan_data
->shm_fd
= -1;
312 chan_data
->wait_fd
= -1;
313 chan
= shmp(handle
, handle
->chan
);
315 for (k
= 0; k
< nr_check
; k
++) {
316 struct object_data
*stream_data
= &stream_datas
[k
];
318 if (!stream_data
->handle
)
321 ret
= channel_handle_add_stream(handle
,
323 stream_data
->wait_fd
,
324 stream_data
->memory_map_size
);
326 printf("add stream error\n");
329 stream_data
->shm_fd
= -1;
330 stream_data
->wait_fd
= -1;
335 channel_destroy(chan
, handle
, 1);
340 void unmap_channel(struct shm_handle
*handle
)
342 struct channel
*chan
;
344 chan
= shmp(handle
, handle
->chan
);
346 channel_destroy(chan
, handle
, 1);
350 int consume_stream(struct shm_handle
*handle
, int cpu
, char *outfile
)
352 struct channel
*chan
;
353 struct lib_ring_buffer
*buf
;
356 uint64_t memory_map_size
;
358 chan
= shmp(handle
, handle
->chan
);
361 buf
= channel_get_ring_buffer(&chan
->backend
.config
,
362 chan
, cpu
, handle
, &shm_fd
, &wait_fd
, &memory_map_size
);
365 ret
= lib_ring_buffer_open_read(buf
, handle
, 1);
371 outfd
= open(outfile
, O_WRONLY
| O_CREAT
| O_LARGEFILE
| O_TRUNC
,
372 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
374 perror("open output");
378 printf("Waiting for buffer data for %s\n", outfile
);
380 unsigned long read_size
;
381 unsigned long copy_size
;
384 ret
= lib_ring_buffer_get_next_subbuf(buf
, handle
);
385 printf("get next ret %d\n", ret
);
388 if (ret
== -EAGAIN
) {
393 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret
);
396 read_size
= lib_ring_buffer_get_read_data_size(
397 &chan
->backend
.config
, buf
, handle
);
398 read_size
= PAGE_ALIGN(read_size
);
399 ptr
= lib_ring_buffer_read_offset_address(
400 &buf
->backend
, 0, handle
);
401 printf("WRITE: copy %lu bytes\n", read_size
);
402 copy_size
= write(outfd
, ptr
, read_size
);
403 if (copy_size
< read_size
) {
404 printf("write issue: copied %zd, expected %lu\n", copy_size
, read_size
);
406 lib_ring_buffer_put_next_subbuf(buf
, handle
);
416 lib_ring_buffer_release_read(buf
, handle
, 1);
421 int consume_buffers(void)
426 for (i
= 0; i
< NR_SESSIONS
; i
++) {
427 char pathname
[PATH_MAX
];
428 struct shm_handle
*handle
;
430 snprintf(pathname
, PATH_MAX
- 1, "/tmp/testtrace%u", i
);
431 old_umask
= umask(0);
432 ret
= mkdir(pathname
, S_IRWXU
| S_IRWXG
);
433 if (ret
&& errno
!= EEXIST
) {
441 handle
= map_channel(&metadata_data
[i
],
442 &metadata_stream_data
[i
], 1);
445 snprintf(pathname
, PATH_MAX
- 1,
446 "/tmp/testtrace%u/metadata", i
);
447 ret
= consume_stream(handle
, -1, pathname
);
448 if (ret
&& ret
!= -ENOENT
) {
449 printf("Error in consume_stream\n");
452 unmap_channel(handle
);
454 /* copy binary data */
455 for (j
= 0; j
< NR_CHANNELS
; j
++) {
456 handle
= map_channel(&channel_data
[i
][j
],
457 stream_data
[i
][j
], MAX_NR_STREAMS
);
460 for (k
= 0; k
< MAX_NR_STREAMS
; k
++) {
461 snprintf(pathname
, PATH_MAX
- 1,
462 "/tmp/testtrace%u/data_%u", i
, k
);
463 ret
= consume_stream(handle
, k
, pathname
);
464 if (ret
&& ret
!= -ENOENT
) {
465 printf("Error in consume_stream\n");
469 unmap_channel(handle
);
476 int send_app_msgs(int sock
)
478 struct lttcomm_ust_msg lum
;
479 struct lttcomm_ust_reply lur
;
482 for (i
= 0; i
< NR_SESSIONS
; i
++) {
484 memset(&lum
, 0, sizeof(lum
));
485 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
486 lum
.cmd
= LTTNG_UST_SESSION
;
487 ret
= send_app_cmd(sock
, &lum
, &lur
);
490 session_handle
[i
] = lur
.ret_val
;
491 printf("received session handle %u\n", session_handle
[i
]);
493 /* Create metadata channel */
494 memset(&lum
, 0, sizeof(lum
));
495 lum
.handle
= session_handle
[i
];
496 lum
.cmd
= LTTNG_UST_METADATA
;
497 lum
.u
.channel
.overwrite
= 0;
498 lum
.u
.channel
.subbuf_size
= 32768;
499 lum
.u
.channel
.num_subbuf
= 4;
500 lum
.u
.channel
.switch_timer_interval
= 0;
501 lum
.u
.channel
.read_timer_interval
= 0;
502 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
503 ret
= send_app_cmd(sock
, &lum
, &lur
);
506 metadata_data
[i
].handle
= lur
.ret_val
;
507 printf("received metadata handle %u\n", metadata_data
[i
].handle
);
508 if (lur
.ret_code
== LTTCOMM_OK
) {
511 metadata_data
[i
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
513 len
= lttcomm_recv_fd(sock
);
516 metadata_data
[i
].shm_fd
= len
;
518 len
= lttcomm_recv_fd(sock
);
521 metadata_data
[i
].wait_fd
= len
;
524 ret
= open_streams(sock
, metadata_data
[i
].handle
,
525 &metadata_stream_data
[i
], 1);
527 printf("Error in open_streams\n");
531 /* Create channels */
532 for (j
= 0; j
< NR_CHANNELS
; j
++) {
533 memset(&lum
, 0, sizeof(lum
));
534 lum
.handle
= session_handle
[i
];
535 lum
.cmd
= LTTNG_UST_CHANNEL
;
536 //lum.u.channel.overwrite = 0;
537 lum
.u
.channel
.overwrite
= 1;
538 lum
.u
.channel
.subbuf_size
= 32768;
539 lum
.u
.channel
.num_subbuf
= 8;
540 //lum.u.channel.num_subbuf = 4;
541 //lum.u.channel.num_subbuf = 2;
542 lum
.u
.channel
.switch_timer_interval
= 0;
543 lum
.u
.channel
.read_timer_interval
= 0;
544 lum
.u
.channel
.output
= LTTNG_UST_MMAP
;
545 ret
= send_app_cmd(sock
, &lum
, &lur
);
548 channel_data
[i
][j
].handle
= lur
.ret_val
;
549 printf("received channel handle %u\n", channel_data
[i
][j
].handle
);
550 if (lur
.ret_code
== LTTCOMM_OK
) {
553 channel_data
[i
][j
].memory_map_size
= lur
.u
.channel
.memory_map_size
;
555 len
= lttcomm_recv_fd(sock
);
558 channel_data
[i
][j
].shm_fd
= len
;
560 len
= lttcomm_recv_fd(sock
);
563 channel_data
[i
][j
].wait_fd
= len
;
567 for (k
= 0; k
< NR_EVENTS
; k
++) {
568 memset(&lum
, 0, sizeof(lum
));
569 lum
.handle
= channel_data
[i
][j
].handle
;
570 lum
.cmd
= LTTNG_UST_EVENT
;
571 strncpy(lum
.u
.event
.name
, evname
[k
],
572 LTTNG_UST_SYM_NAME_LEN
);
573 lum
.u
.event
.instrumentation
= LTTNG_UST_TRACEPOINT
;
574 ret
= send_app_cmd(sock
, &lum
, &lur
);
577 event_handle
[i
][j
][k
] = lur
.ret_val
;
578 printf("received event handle %u\n", event_handle
[i
][j
][k
]);
581 /* Get references to channel streams */
582 ret
= open_streams(sock
, channel_data
[i
][j
].handle
,
583 stream_data
[i
][j
], MAX_NR_STREAMS
);
585 printf("Error in open_streams\n");
590 memset(&lum
, 0, sizeof(lum
));
591 lum
.handle
= session_handle
[i
];
592 lum
.cmd
= LTTNG_UST_SESSION_START
;
593 ret
= send_app_cmd(sock
, &lum
, &lur
);
596 printf("Session handle %u started.\n", session_handle
[i
]);
599 /* Tell application registration is done */
600 memset(&lum
, 0, sizeof(lum
));
601 lum
.handle
= LTTNG_UST_ROOT_HANDLE
;
602 lum
.cmd
= LTTNG_UST_REGISTER_DONE
;
603 ret
= send_app_cmd(sock
, &lum
, &lur
);
606 printf("Registration done acknowledged.\n");
610 ret
= consume_buffers();
612 printf("Error in consume_buffers\n");
616 for (i
= 0; i
< NR_SESSIONS
; i
++) {
617 /* Release channels */
618 for (j
= 0; j
< NR_CHANNELS
; j
++) {
619 /* Release streams */
620 ret
= close_streams(sock
, stream_data
[i
][j
],
626 for (k
= 0; k
< NR_EVENTS
; k
++) {
627 memset(&lum
, 0, sizeof(lum
));
628 lum
.handle
= event_handle
[i
][j
][k
];
629 lum
.cmd
= LTTNG_UST_RELEASE
;
630 ret
= send_app_cmd(sock
, &lum
, &lur
);
634 memset(&lum
, 0, sizeof(lum
));
635 lum
.handle
= channel_data
[i
][j
].handle
;
636 lum
.cmd
= LTTNG_UST_RELEASE
;
637 ret
= send_app_cmd(sock
, &lum
, &lur
);
640 if (channel_data
[i
][j
].shm_fd
>= 0) {
641 ret
= close(channel_data
[i
][j
].shm_fd
);
645 if (channel_data
[i
][j
].wait_fd
>= 0) {
646 ret
= close(channel_data
[i
][j
].wait_fd
);
652 /* Release metadata channel */
653 ret
= close_streams(sock
, &metadata_stream_data
[i
], 1);
657 memset(&lum
, 0, sizeof(lum
));
658 lum
.handle
= metadata_data
[i
].handle
;
659 lum
.cmd
= LTTNG_UST_RELEASE
;
660 ret
= send_app_cmd(sock
, &lum
, &lur
);
663 if (metadata_data
[i
].shm_fd
>= 0) {
664 ret
= close(metadata_data
[i
].shm_fd
);
668 if (metadata_data
[i
].wait_fd
>= 0) {
669 ret
= close(metadata_data
[i
].wait_fd
);
674 /* Release session */
675 memset(&lum
, 0, sizeof(lum
));
676 lum
.handle
= session_handle
[i
];
677 lum
.cmd
= LTTNG_UST_RELEASE
;
678 ret
= send_app_cmd(sock
, &lum
, &lur
);
687 * Using fork to set umask in the child process (not multi-thread safe). We
688 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
689 * the shm and does not let everybody modify it, to ensure safety against
690 * shm_unlink) by simply letting the mmap fail and retrying after a few
691 * seconds. For global shm, everybody has rw access to it until the sessiond
694 static int get_wait_shm(char *shm_path
, size_t mmap_size
, int global
)
696 int wait_shm_fd
, ret
;
699 /* Default permissions */
700 mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
702 /* Change owner of the shm path */
704 ret
= chown(shm_path
, 0, 0);
706 if (errno
!= ENOENT
) {
707 perror("chown wait shm");
713 * If global session daemon, any application can register so the shm
714 * needs to be set in read-only mode for others.
718 ret
= chown(shm_path
, getuid(), getgid());
720 if (errno
!= ENOENT
) {
721 perror("chown wait shm");
728 * Set permissions to the shm even if we did not create the shm.
730 ret
= chmod(shm_path
, mode
);
732 if (errno
!= ENOENT
) {
733 perror("chmod wait shm");
739 * We're alone in a child process, so we can modify the process-wide
745 * Try creating shm (or get rw access). We don't do an exclusive open,
746 * because we allow other processes to create+ftruncate it concurrently.
748 wait_shm_fd
= shm_open(shm_path
, O_RDWR
| O_CREAT
, mode
);
749 if (wait_shm_fd
< 0) {
750 perror("shm_open wait shm");
754 ret
= ftruncate(wait_shm_fd
, mmap_size
);
756 perror("ftruncate wait shm");
760 ret
= fchmod(wait_shm_fd
, mode
);
766 printf("Got the wait shm fd %d\n", wait_shm_fd
);
771 printf("Failing to get the wait shm fd\n");
776 int update_futex(int fd
, int active
)
778 size_t mmap_size
= sysconf(_SC_PAGE_SIZE
);
782 wait_shm_mmap
= mmap(NULL
, mmap_size
, PROT_READ
| PROT_WRITE
,
784 if (wait_shm_mmap
== MAP_FAILED
) {
790 uatomic_set((int32_t *) wait_shm_mmap
, 1);
791 futex_async((int32_t *) wait_shm_mmap
, FUTEX_WAKE
,
792 INT_MAX
, NULL
, NULL
, 0);
794 uatomic_set((int32_t *) wait_shm_mmap
, 0);
796 ret
= munmap(wait_shm_mmap
, mmap_size
);
798 perror("Error unmapping wait shm");
807 * Set open files limit to unlimited. This daemon can open a large number of
808 * file descriptors in order to consumer multiple kernel traces.
810 static void set_ulimit(void)
816 * If not root, we cannot increase our max open files. But our
817 * scope is then limited to processes from a single user.
821 /* The kernel does not allowed an infinite limit for open files */
822 lim
.rlim_cur
= 65535;
823 lim
.rlim_max
= 65535;
825 ret
= setrlimit(RLIMIT_NOFILE
, &lim
);
827 perror("failed to set open files limit");
831 int main(int argc
, char **argv
)
833 const char *home_dir
;
834 int ret
, wait_shm_fd
;
835 struct sigaction act
;
836 mode_t old_umask
= 0;
841 memset(&act
, 0, sizeof(act
));
842 ret
= sigemptyset(&act
.sa_mask
);
844 perror("sigemptyset");
848 act
.sa_handler
= SIG_IGN
;
849 ret
= sigaction(SIGPIPE
, &act
, NULL
);
856 act
.sa_handler
= handle_signals
;
857 ret
= sigaction(SIGTERM
, &act
, NULL
);
863 ret
= sigaction(SIGINT
, &act
, NULL
);
869 if (geteuid() == 0) {
870 ret
= mkdir(LTTNG_RUNDIR
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
871 if (ret
&& errno
!= EEXIST
) {
875 wait_shm_fd
= get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH
,
876 sysconf(_SC_PAGE_SIZE
), 1);
877 if (wait_shm_fd
< 0) {
878 perror("global wait shm error");
881 strcpy(apps_sock_path
, DEFAULT_GLOBAL_APPS_UNIX_SOCK
);
882 old_umask
= umask(0);
884 snprintf(local_apps_wait_shm_path
, PATH_MAX
,
885 DEFAULT_HOME_APPS_WAIT_SHM_PATH
, getuid());
886 wait_shm_fd
= get_wait_shm(local_apps_wait_shm_path
,
887 sysconf(_SC_PAGE_SIZE
), 0);
888 if (wait_shm_fd
< 0) {
889 perror("local wait shm error");
892 home_dir
= (const char *) getenv("HOME");
894 perror("getenv error");
897 snprintf(apps_sock_path
, PATH_MAX
,
898 DEFAULT_HOME_APPS_UNIX_SOCK
, home_dir
);
901 ret
= lttcomm_create_unix_sock(apps_sock_path
);
903 perror("create error");
909 /* File permission MUST be 666 */
910 ret
= chmod(apps_sock_path
,
911 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
913 printf("Set file permissions failed: %s\n", apps_sock_path
);
919 ret
= lttcomm_listen_unix_sock(apps_socket
);
921 perror("listen error");
925 /* wake up futexes */
926 ret
= update_futex(wait_shm_fd
, 1);
928 fprintf(stderr
, "Error wakeup futex\n");
942 char name
[16]; /* Process name */
949 printf("Accepting application registration\n");
950 sock
= lttcomm_accept_unix_sock(apps_socket
);
952 perror("accept error");
957 * Basic recv here to handle the very simple data
958 * that the libust send to register (reg_msg).
960 len
= lttcomm_recv_unix_sock(sock
, ®_msg
, sizeof(reg_msg
));
961 if (len
< 0 || len
!= sizeof(reg_msg
)) {
962 perror("lttcomm_recv_unix_sock");
965 memcpy(bufname
, reg_msg
.name
, 16);
967 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
968 bufname
, reg_msg
.pid
, reg_msg
.ppid
, reg_msg
.uid
,
969 reg_msg
.gid
, reg_msg
.major
, reg_msg
.minor
);
970 ret
= send_app_msgs(sock
);
972 printf("Error in send_app_msgs.\n");
979 printf("quitting.\n");
980 /* Let applications know we are not responding anymore */
981 ret
= update_futex(wait_shm_fd
, 0);
983 fprintf(stderr
, "Error wakeup futex\n");