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: