From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This adds handling of systemd NOTIFY_SOCKET so application using mainloop instance do properly notify systemd what is their state. --- Makefile.am | 8 ++- src/shared/mainloop-glib.c | 8 +++ src/shared/mainloop-notify.c | 104 +++++++++++++++++++++++++++++++++++ src/shared/mainloop-notify.h | 25 +++++++++ src/shared/mainloop.c | 12 ++++ src/shared/mainloop.h | 1 + 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/shared/mainloop-notify.c create mode 100644 src/shared/mainloop-notify.h diff --git a/Makefile.am b/Makefile.am index 0b26ccc3e..124c32482 100644 --- a/Makefile.am +++ b/Makefile.am @@ -130,12 +130,16 @@ endif src_libshared_glib_la_SOURCES = $(shared_sources) \ src/shared/io-glib.c \ src/shared/timeout-glib.c \ - src/shared/mainloop-glib.c + src/shared/mainloop-glib.c \ + src/shared/mainloop-notify.h \ + src/shared/mainloop-notify.c src_libshared_mainloop_la_SOURCES = $(shared_sources) \ src/shared/io-mainloop.c \ src/shared/timeout-mainloop.c \ - src/shared/mainloop.h src/shared/mainloop.c + src/shared/mainloop.h src/shared/mainloop.c \ + src/shared/mainloop-notify.h \ + src/shared/mainloop-notify.c if ELL src_libshared_ell_la_SOURCES = $(shared_sources) \ diff --git a/src/shared/mainloop-glib.c b/src/shared/mainloop-glib.c index 8436969bb..9d588e8c5 100644 --- a/src/shared/mainloop-glib.c +++ b/src/shared/mainloop-glib.c @@ -36,6 +36,7 @@ #include <glib.h> #include "mainloop.h" +#include "mainloop-notify.h" static GMainLoop *main_loop; static int exit_status; @@ -43,6 +44,7 @@ static int exit_status; void mainloop_init(void) { main_loop = g_main_loop_new(NULL, FALSE); + mainloop_notify_init(); } void mainloop_quit(void) @@ -70,11 +72,17 @@ int mainloop_run(void) if (!main_loop) return -EINVAL; + mainloop_notify("READY=1"); + g_main_loop_run(main_loop); + mainloop_notify("STOPPING=1"); + g_main_loop_unref(main_loop); main_loop = NULL; + mainloop_notify_exit(); + return exit_status; } diff --git a/src/shared/mainloop-notify.c b/src/shared/mainloop-notify.c new file mode 100644 index 000000000..fef333c24 --- /dev/null +++ b/src/shared/mainloop-notify.c @@ -0,0 +1,104 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#include <sys/socket.h> +#include <sys/un.h> + +#include "mainloop.h" +#include "mainloop-notify.h" + +static char *notify_sock; +static int notify_fd = -1; + +void mainloop_notify_init(void) +{ + const char *sock; + + sock = getenv("NOTIFY_SOCKET"); + if (!sock) + return; + + /* check for abstract socket or absolute path */ + if (sock[0] != '@' && sock[0] != '/') + return; + + notify_sock = strdup(sock); + + notify_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); +} + +void mainloop_notify_exit(void) +{ + if (notify_fd > 0) { + close(notify_fd); + notify_fd = -1; + } + + free(notify_sock); + notify_sock = NULL; +} + +int mainloop_notify(const char *state) +{ + struct sockaddr_un addr; + struct msghdr msghdr; + struct iovec iovec; + + if (notify_fd <= 0) + return -ENOTCONN; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, notify_sock, sizeof(addr.sun_path) - 1); + + if (addr.sun_path[0] == '@') + addr.sun_path[0] = '\0'; + + memset(&iovec, 0, sizeof(iovec)); + iovec.iov_base = (char *) state; + iovec.iov_len = strlen(state); + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = &addr; + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + + strlen(notify_sock); + + if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) + msghdr.msg_namelen = sizeof(struct sockaddr_un); + + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + + return sendmsg(notify_fd, &msghdr, MSG_NOSIGNAL); +} diff --git a/src/shared/mainloop-notify.h b/src/shared/mainloop-notify.h new file mode 100644 index 000000000..721b5fbed --- /dev/null +++ b/src/shared/mainloop-notify.h @@ -0,0 +1,25 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +void mainloop_notify_init(void); +void mainloop_notify_exit(void); diff --git a/src/shared/mainloop.c b/src/shared/mainloop.c index e6ab9c43d..9255e6e0e 100644 --- a/src/shared/mainloop.c +++ b/src/shared/mainloop.c @@ -30,13 +30,17 @@ #include <errno.h> #include <unistd.h> #include <stdlib.h> +#include <stddef.h> #include <string.h> #include <signal.h> #include <sys/signalfd.h> #include <sys/timerfd.h> #include <sys/epoll.h> +#include <sys/socket.h> +#include <sys/un.h> #include "mainloop.h" +#include "mainloop-notify.h" #define MAX_EPOLL_EVENTS 10 @@ -83,6 +87,8 @@ void mainloop_init(void) mainloop_list[i] = NULL; epoll_terminate = 0; + + mainloop_notify_init(); } void mainloop_quit(void) @@ -141,6 +147,8 @@ int mainloop_run(void) } } + mainloop_notify("READY=1"); + while (!epoll_terminate) { struct epoll_event events[MAX_EPOLL_EVENTS]; int n, nfds; @@ -180,9 +188,13 @@ int mainloop_run(void) } } + mainloop_notify("STOPPING=1"); + close(epoll_fd); epoll_fd = 0; + mainloop_notify_exit(); + return exit_status; } diff --git a/src/shared/mainloop.h b/src/shared/mainloop.h index b83caabc8..7ae6b3c90 100644 --- a/src/shared/mainloop.h +++ b/src/shared/mainloop.h @@ -49,3 +49,4 @@ int mainloop_remove_timeout(int id); int mainloop_set_signal(sigset_t *mask, mainloop_signal_func callback, void *user_data, mainloop_destroy_func destroy); +int mainloop_notify(const char *state); -- 2.17.2