Skip to content

Commit 05398cd

Browse files
benh-debianchucklever
authored andcommitted
netlink: Introduce event loop and use signalfd to catch signals
Currently we use a blocking netlink socket, which is not compatible with handling signals gracefully. To handle SIGINT properly: - Set the netlink socket to be non-blocking - Block SIGINT and create a signalfd() to receive it - Poll the netlink socket and signal fd in a loop Signed-off-by: Ben Hutchings <benh@debian.org>
1 parent ea8177d commit 05398cd

File tree

1 file changed

+48
-4
lines changed

1 file changed

+48
-4
lines changed

src/tlshd/netlink.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <sys/types.h>
2424
#include <sys/stat.h>
2525
#include <sys/socket.h>
26+
#include <sys/signalfd.h>
2627

2728
#include <stdbool.h>
2829
#include <unistd.h>
@@ -106,6 +107,9 @@ tlshd_accept_nl_policy[HANDSHAKE_A_ACCEPT_MAX + 1] = {
106107

107108
static struct nl_sock *tlshd_notification_nls;
108109

110+
static sigset_t tlshd_sig_poll_mask;
111+
static int tlshd_sig_poll_fd;
112+
109113
static int tlshd_genl_event_handler(struct nl_msg *msg,
110114
__attribute__ ((unused)) void *arg)
111115
{
@@ -127,6 +131,9 @@ static int tlshd_genl_event_handler(struct nl_msg *msg,
127131

128132
if (!fork()) {
129133
/* child */
134+
close(tlshd_sig_poll_fd);
135+
sigprocmask(SIG_UNBLOCK, &tlshd_sig_poll_mask, NULL);
136+
130137
nlmsg_free(msg);
131138
tlshd_genl_sock_close(tlshd_notification_nls);
132139

@@ -146,8 +153,13 @@ static int tlshd_genl_event_handler(struct nl_msg *msg,
146153
*/
147154
void tlshd_genl_dispatch(void)
148155
{
156+
struct pollfd poll_fds[2];
149157
int err, mcgrp;
150158

159+
/* Initialise signal poll mask */
160+
sigemptyset(&tlshd_sig_poll_mask);
161+
sigaddset(&tlshd_sig_poll_mask, SIGINT);
162+
151163
err = tlshd_genl_sock_open(&tlshd_notification_nls);
152164
if (err)
153165
return;
@@ -174,14 +186,46 @@ void tlshd_genl_dispatch(void)
174186
}
175187

176188
nl_socket_disable_seq_check(tlshd_notification_nls);
177-
while (true) {
178-
err = nl_recvmsgs_default(tlshd_notification_nls);
179-
if (err < 0) {
180-
tlshd_log_nl_error("nl_recvmsgs", err);
189+
190+
err = nl_socket_set_nonblocking(tlshd_notification_nls);
191+
if (err != NLE_SUCCESS) {
192+
tlshd_log_nl_error("nl_socket_set_nonblocking", err);
193+
goto out_close;
194+
}
195+
196+
if (sigprocmask(SIG_BLOCK, &tlshd_sig_poll_mask, NULL)) {
197+
tlshd_log_perror("sigprocmask");
198+
goto out_close;
199+
}
200+
201+
tlshd_sig_poll_fd = signalfd(-1, &tlshd_sig_poll_mask,
202+
SFD_NONBLOCK | SFD_CLOEXEC);
203+
if (tlshd_sig_poll_fd < 0) {
204+
tlshd_log_perror("signalfd");
205+
goto out_close;
206+
}
207+
208+
poll_fds[0].fd = nl_socket_get_fd(tlshd_notification_nls);
209+
poll_fds[0].events = POLLIN;
210+
poll_fds[1].fd = tlshd_sig_poll_fd;
211+
poll_fds[1].events = POLLIN;
212+
213+
while (poll(poll_fds, ARRAY_SIZE(poll_fds), -1) >= 0) {
214+
if (poll_fds[1].revents)
215+
/* exit signal received */
181216
break;
217+
218+
if (poll_fds[0].revents) {
219+
err = nl_recvmsgs_default(tlshd_notification_nls);
220+
if (err < 0) {
221+
tlshd_log_nl_error("nl_recvmsgs", err);
222+
break;
223+
}
182224
}
183225
};
184226

227+
close(tlshd_sig_poll_fd);
228+
185229
out_close:
186230
tlshd_genl_sock_close(tlshd_notification_nls);
187231
}

0 commit comments

Comments
 (0)