From 0b02cd2690c1777a989c806bc55629e6e9018a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sat, 29 Aug 2015 12:23:42 +0000 Subject: [PATCH] [mmap] handle SIGBUS in network; those get triggered if the file gets smaller during reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Stefan Bühler git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3031 152afb58-edef-0310-8abb-c4023f1b3aa9 --- NEWS | 1 + src/network_write_mmap.c | 43 ++++++++++++++++++++++++++++++++++++++-- 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 +#include #include #include @@ -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: