Permalink
Browse files

Fix a potential infinite hang found in sigrecv_ack()

  • Loading branch information...
Shawn Wagner
Shawn Wagner committed Jan 9, 2018
1 parent 8bae29b commit 3e4caec531fe4d915a59b2c56b3b04619757f061
Showing with 38 additions and 2 deletions.
  1. +3 −0 CHANGES.187.md
  2. +35 −2 src/sig.c
View
@@ -39,6 +39,9 @@ Fixes
* Connecting with a web browser to a mush without a mud_url config
option set caused an infinite refresh loop. Reported by
grapenut. [1149]
* Make sure sigrecv_ack() won't hang the mush if it somehow gets
called at the wrong time. Also fix a file descriptor leak in the
signal handling code. [SW]
Documentation
-------------
View
@@ -8,6 +8,7 @@
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
@@ -17,8 +18,10 @@
#ifdef HAVE_SYS_EVENTFD_H
#include <sys/eventfd.h>
#endif
#include <fcntl.h>
#include "conf.h"
#include "mysocket.h"
#include "sig.h"
int sigrecv_fd = -1;
@@ -39,17 +42,46 @@ void
sigrecv_setup(void)
{
#ifdef HAVE_EVENTFD
sigrecv_fd = signotifier_fd = eventfd(0, EFD_CLOEXEC);
sigrecv_fd = signotifier_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (sigrecv_fd < 0)
perror("sigrecv_setup: eventfd");
#else
int fds[2];
int flags;
if (pipe(fds) < 0) {
perror("sigrecv_setup: pipe");
return;
}
sigrecv_fd = fds[0];
signotifier_fd = fds[1];
#ifdef HAVE_FCNTL
flags = fcntl(sigrecv_fd, F_GETFD);
if (flags >= 0) {
flags |= FD_CLOEXEC;
if (fcntl(sigrecv_fd, F_SETFD, flags) < 0)
perror("sigrecv_setup: fcntl F_SETFD:");
} else {
perror("sigrecv_setup: fcntl F_GETFD:");
}
flags = fcntl(signotifier_fd, F_GETFD);
if (flags >= 0) {
flags |= FD_CLOEXEC;
if (fcntl(signotifier_fd, F_SETFD, flags) < 0)
perror("sigrecv_setup: fcntl F_SETFD:");
} else {
perror("sigrecv_setup: fcntl F_GETFD:");
}
flags = fcntl(signotifier_fd, F_GETFL);
if (flags >= 0) {
flags |= O_NDELAY;
if (fcntl(signotifier_fd, F_SETFL, flags) < 0)
perror("sigrecv_setup: fcntl F_SETFL:");
} else {
perror("sigrecv_setup: fcntl F_GETFL:");
}
#endif
#endif
}
@@ -71,7 +103,8 @@ sigrecv_ack(void)
{
int64_t data;
if (read(sigrecv_fd, &data, sizeof data) < 0) {
perror("sigrecv_ack: read");
if (errno != EAGAIN)
perror("sigrecv_ack: read");
}
}

0 comments on commit 3e4caec

Please sign in to comment.