summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Bühler <stbuehler@web.de>2015-08-29 12:23:42 +0000
committerStefan Bühler <stbuehler@web.de>2015-08-29 12:23:42 +0000
commit0b02cd2690c1777a989c806bc55629e6e9018a9a (patch)
treed2079abf503b38c4091f01e1d1e518de733b3267
parent68284bd7f11defea1a43cf987f501415ed29f4a5 (diff)
downloadlighttpd-git-0b02cd2690c1777a989c806bc55629e6e9018a9a.tar.gz
[mmap] handle SIGBUS in network; those get triggered if the file gets smaller during reading
From: Stefan Bühler <stbuehler@web.de> git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3031 152afb58-edef-0310-8abb-c4023f1b3aa9
-rw-r--r--NEWS1
-rw-r--r--src/network_write_mmap.c43
2 files changed, 42 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index e0b0940f..d1852a07 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ NEWS
* [mod_cgi] rewrite mmap and generic (post body) send error handling
* [mmap] fix mmap alignment
* [plugins] when modules are linked statically still only load the modules given in the config
+ * [mmap] handle SIGBUS in network; those get triggered if the file gets smaller during reading
- 1.4.36 - 2015-07-26
* use keep-alive timeout while waiting for HTTP headers; use always the read timeout while waiting for the HTTP body
diff --git a/src/network_write_mmap.c b/src/network_write_mmap.c
index 9ff3ae96..445ea390 100644
--- a/src/network_write_mmap.c
+++ b/src/network_write_mmap.c
@@ -4,6 +4,8 @@
#include "log.h"
#include "sys-mmap.h"
+#include <setjmp.h>
+#include <signal.h>
#include <unistd.h>
#include <errno.h>
@@ -23,6 +25,15 @@ off_t mmap_align_offset(off_t start) {
#if defined(USE_MMAP)
+static volatile int sigbus_jmp_valid;
+static sigjmp_buf sigbus_jmp;
+
+static void sigbus_handler(int sig) {
+ UNUSED(sig);
+ if (sigbus_jmp_valid) siglongjmp(sigbus_jmp, 1);
+ log_failed_assert(__FILE__, __LINE__, "SIGBUS");
+}
+
#if 0
/* read mmap()ed data into local buffer */
#define LOCAL_BUFFERING 1
@@ -51,6 +62,24 @@ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkque
if (0 != network_open_file_chunk(srv, con, cq)) return -1;
+ /* setup SIGBUS handler, but don't activate sigbus_jmp_valid yet */
+ if (0 != sigsetjmp(sigbus_jmp, 1)) {
+ sigbus_jmp_valid = 0;
+
+ log_error_write(srv, __FILE__, __LINE__, "sbd", "SIGBUS in mmap:",
+ c->file.name, c->file.fd);
+
+ munmap(c->file.mmap.start, c->file.mmap.length);
+ c->file.mmap.start = MAP_FAILED;
+#ifdef LOCAL_BUFFERING
+ buffer_reset(c->mem);
+#endif
+
+ return -1;
+ }
+
+ signal(SIGBUS, sigbus_handler);
+
/* mmap the buffer if offset is outside old mmap area or not mapped at all */
if (MAP_FAILED == c->file.mmap.start
|| offset < c->file.mmap.offset
@@ -97,7 +126,9 @@ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkque
}
#if defined(LOCAL_BUFFERING)
+ sigbus_jmp_valid = 1;
buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
+ sigbus_jmp_valid = 0;
#else
# if defined(HAVE_MADVISE)
/* don't advise files < 64Kb */
@@ -124,8 +155,16 @@ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkque
data = c->file.mmap.start + mmap_offset;
#endif
+ sigbus_jmp_valid = 1;
+#if defined(__WIN32)
+ r = send(fd, data, toSend, 0);
+#else /* __WIN32 */
+ r = write(fd, data, toSend);
+#endif /* __WIN32 */
+ sigbus_jmp_valid = 0;
+
#if defined(__WIN32)
- if ((r = send(fd, data, toSend, 0)) < 0) {
+ if (r < 0) {
int lastError = WSAGetLastError();
switch (lastError) {
case WSAEINTR:
@@ -142,7 +181,7 @@ int network_write_file_chunk_mmap(server *srv, connection *con, int fd, chunkque
}
}
#else /* __WIN32 */
- if ((r = write(fd, data, toSend)) < 0) {
+ if (r < 0) {
switch (errno) {
case EAGAIN:
case EINTR: