diff --git a/bin/release/redis-2.8.12.zip b/bin/release/redis-2.8.12.zip index 7c73e8899cd85c39b368a1220c931433e30f94ed..61be99855221e334f3dfe6858bea08a8b033a69c 100644 Binary files a/bin/release/redis-2.8.12.zip and b/bin/release/redis-2.8.12.zip differ diff --git a/src/Win32_Interop/Win32_FDAPI.cpp b/src/Win32_Interop/Win32_FDAPI.cpp index add7c8a01844f6e3c6fc90b6c11480b37a733109..6bfffcc0e2823d9f6c2f764e919ad91dcc7da174 100644 --- a/src/Win32_Interop/Win32_FDAPI.cpp +++ b/src/Win32_Interop/Win32_FDAPI.cpp @@ -45,6 +45,7 @@ redis_WSACleanup WSACleanup = NULL; redis_WSAGetOverlappedResult WSAGetOverlappedResult = NULL; // other API forwards +redis_fwrite fdapi_fwrite = NULL; redis_setmode fdapi_setmode = NULL; redis_select select = NULL; redis_ntohl ntohl = NULL; @@ -906,6 +907,10 @@ int redis_setmode_impl(int fd,int mode) { return crtsetmode(fd,mode); } +size_t redis_fwrite_impl(const void * _Str, size_t _Size, size_t _Count, FILE * _File) { + return crtfwrite(_Str, _Size, _Count, _File); +} + auto f_select = dllfunctor_stdcall("ws2_32.dll", "select"); int redis_select_impl(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) { try { @@ -1053,6 +1058,7 @@ private: inet_addr = redis_inet_addr_impl; gethostbyname = redis_gethostbyname_impl; inet_ntoa = redis_inet_ntoa_impl; + fdapi_fwrite = redis_fwrite_impl; fdapi_setmode = redis_setmode_impl; WSASetLastError = redis_WSASetLastError_impl; WSAGetLastError = redis_WSAGetLastError_impl; diff --git a/src/Win32_Interop/Win32_FDAPI.h b/src/Win32_Interop/Win32_FDAPI.h index 298d6ee16bd34b599d930addb7689ae796cbcd6c..3cf7a37749179ec4643875bf4e2d4477fc611222 100644 --- a/src/Win32_Interop/Win32_FDAPI.h +++ b/src/Win32_Interop/Win32_FDAPI.h @@ -40,6 +40,7 @@ typedef int ssize_t; #define INCL_WINSOCK_API_PROTOTYPES 0 // Important! Do not include Winsock API definitions to avoid conflicts with API entry points defnied below. #include #include +#include // the following are required to be defined before WS2tcpip is included. typedef void (*redis_WSASetLastError)(int iError); @@ -149,6 +150,7 @@ typedef BOOL (*redis_WSAGetOverlappedResult)(int rfd,LPWSAOVERLAPPED lpOverlappe // other API forwards typedef int (*redis_setmode)(int fd,int mode); +typedef size_t (*redis_fwrite)(const void * _Str, size_t _Size, size_t _Count, FILE * _File); // API prototypes must match the unix implementation typedef int (*redis_socket)(int af,int type,int protocol); @@ -227,6 +229,7 @@ extern redis_getpeername getpeername; extern redis_getsockname getsockname; extern redis_ntohs ntohs; extern redis_setmode fdapi_setmode; +extern redis_fwrite fdapi_fwrite; extern redis_select select; extern redis_ntohl ntohl; @@ -250,6 +253,7 @@ int FDAPI_UpdateAcceptContext( int fd ); #ifndef FDAPI_NOCRTREDEFS #define close(fd) fdapi_close(fd) #define setmode(fd,mode) fdapi_setmode(fd,mode) +#define fwrite(Str, Size, Count, File) fdapi_fwrite(Str,Size,Count,File) #define _get_osfhandle(fd) fdapi_get_osfhandle(fd) #define _INC_STAT_INL diff --git a/src/Win32_Interop/Win32_fdapi_crt.cpp b/src/Win32_Interop/Win32_fdapi_crt.cpp index 36f6bde9accfcb69851ffb4dd07bf5522fdf0d08..f5e8c30c9456112ff83ec840f14cc9dfce789ab2 100644 --- a/src/Win32_Interop/Win32_fdapi_crt.cpp +++ b/src/Win32_Interop/Win32_fdapi_crt.cpp @@ -19,6 +19,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "Win32_fdapi_crt.h" #include #include @@ -47,6 +48,25 @@ int crtsetmode(int fd, int mode) { return ::_setmode(fd, mode); } +size_t crtfwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) { + // fwrite() somehow locks its view of the buffer. If during a fork operation the buffer has not been loaded into the forkee's process space, + // the VEH will be called to load the missing pages. Although the page gets loaded, fwrite() will not see the loaded page. The result is + // that fwrite will fail with errno set to ERROR_INVALID_USER_BUFFER. The fix is to force the buffer into memory before fwrite(). This only + // impacts wirites that straddle page boundaries. + const intptr_t pageSize = 4096; + char* p = (char*)_Str; + char* pageStart = p - ((intptr_t)p % pageSize); + char* pEnd = p + _Size; + if ((intptr_t)(pEnd - pageStart) > pageSize) { + for (size_t n = 0; n < _Size; n++) { + char x = *((char*)_Str + n); + } + } + + return ::fwrite(_Str, _Size, _Count, _File); +} + + int crt_isatty(int fd) { return _isatty(fd); } diff --git a/src/Win32_Interop/Win32_fdapi_crt.h b/src/Win32_Interop/Win32_fdapi_crt.h index b5a291a342f07078a3c9d955bdc01d013b5f8dd6..f7488424ffa1bbaf9749730223dc0c254f8ce75e 100644 --- a/src/Win32_Interop/Win32_fdapi_crt.h +++ b/src/Win32_Interop/Win32_fdapi_crt.h @@ -21,6 +21,7 @@ */ #pragma once #include +#include int crt_close(int fd); int crt_read(int fd, void *buffer, unsigned int count); @@ -28,6 +29,7 @@ int crt_write(int fd, const void *buffer, unsigned int count); int crt_open(const char *filename, int oflag, int pmode); intptr_t crtget_osfhandle(int fd); int crtsetmode(int fd, int mode); +size_t crtfwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File); int crt_isatty(int fd); int crt_access(const char *pathname, int mode); __int64 crt_lseek64(int fd, __int64 offset, int origin); \ No newline at end of file diff --git a/src/rio.c b/src/rio.c index bf981a1f9978154c8a0c0cb202b024f8469d0690..9be9f286721ae418d00ea9eb4da6bd4002b0ac18 100644 --- a/src/rio.c +++ b/src/rio.c @@ -54,7 +54,7 @@ #include "rio.h" #include "util.h" #ifdef _WIN32 -//#include "win32fixes.h" +#include "Win32_Interop\Win32_FDAPI.h" #endif #include "config.h" #include "redis.h" @@ -86,7 +86,6 @@ static off_t rioBufferTell(rio *r) { /* Returns 1 or 0 for success/failure. */ static size_t rioFileWrite(rio *r, const void *buf, size_t len) { size_t retval; - retval = fwrite(buf,len,1,r->io.file.fp); r->io.file.buffered += (off_t)len; diff --git a/src/ziplist.c b/src/ziplist.c index 91cf6267df1f3c3d07272be26f3b2a33d484f6f2..8bdc46cc5ada7f2512e8f456cebef4f6b71bdb64 100644 --- a/src/ziplist.c +++ b/src/ziplist.c @@ -112,6 +112,10 @@ #include "endianconv.h" #include "redisassert.h" +#ifdef _WIN32 +#include "Win32_Interop\Win32_FDAPI.h" +#endif + #define ZIP_END 255 #define ZIP_BIGLEN 254