Skip to content

Commit 7b920de

Browse files
committed
[Fix] Added API mapping for fclose() and fileno().
This fix resolves issue microsoftarchive#235 microsoftarchive#235
1 parent 2b7dc05 commit 7b920de

File tree

6 files changed

+95
-73
lines changed

6 files changed

+95
-73
lines changed

src/Win32_Interop/Win32_FDAPI.cpp

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ redis_WSASocket WSASocket = NULL;
5151

5252
// other API forwards
5353
redis_fwrite fdapi_fwrite = NULL;
54+
redis_fclose fdapi_fclose = NULL;
55+
redis_fileno fdapi_fileno = NULL;
5456
redis_setmode fdapi_setmode = NULL;
5557
redis_select select = NULL;
5658
redis_ntohl ntohl = NULL;
@@ -671,33 +673,26 @@ ssize_t redis_write_impl(int fd, const void *buf, size_t count) {
671673
int redis_fsync_impl(int fd) {
672674
try {
673675
int posixFD = RFDMap::getInstance().lookupPosixFD( fd );
674-
if( posixFD == -1 ) {
675-
// There is one place in Redis where we are not tracking posix FDs because it involves
676-
// direct ocnversion of a FILE* to an FD.
677-
posixFD = fd;
678-
}
679-
680-
HANDLE h = (HANDLE) crtget_osfhandle(posixFD);
681-
DWORD err;
682-
683-
if (h == INVALID_HANDLE_VALUE) {
684-
errno = EBADF;
685-
return -1;
686-
}
676+
if (posixFD != -1) {
677+
HANDLE h = (HANDLE) crtget_osfhandle(posixFD);
678+
if (h == INVALID_HANDLE_VALUE) {
679+
errno = EBADF;
680+
return -1;
681+
}
687682

688-
if (!FlushFileBuffers(h)) {
689-
err = GetLastError();
690-
switch (err) {
691-
case ERROR_INVALID_HANDLE:
692-
errno = EINVAL;
693-
break;
683+
if (!FlushFileBuffers(h)) {
684+
DWORD err = GetLastError();
685+
switch (err) {
686+
case ERROR_INVALID_HANDLE:
687+
errno = EINVAL;
688+
break;
694689

695-
default:
696-
errno = EIO;
690+
default:
691+
errno = EIO;
692+
}
693+
return -1;
697694
}
698-
return -1;
699695
}
700-
701696
return 0;
702697
} CATCH_AND_REPORT()
703698

@@ -708,11 +703,9 @@ int redis_fsync_impl(int fd) {
708703
int redis_fstat_impl(int fd, struct __stat64 *buffer) {
709704
try {
710705
int posixFD = RFDMap::getInstance().lookupPosixFD( fd );
711-
if( posixFD == -1 ) {
712-
posixFD = fd;
706+
if (posixFD != -1) {
707+
return _fstat64(posixFD, buffer);
713708
}
714-
715-
return _fstat64(posixFD, buffer);
716709
} CATCH_AND_REPORT()
717710

718711
errno = EBADF;
@@ -740,26 +733,20 @@ int redis_listen_impl(int sockfd, int backlog) {
740733
int redis_ftruncate_impl(int fd, PORT_LONGLONG length) {
741734
try
742735
{
743-
LARGE_INTEGER l, o;
744-
HANDLE h = INVALID_HANDLE_VALUE;
745-
746736
int posixFD = RFDMap::getInstance().lookupPosixFD( fd );
747-
if( posixFD == -1 ) {
748-
h = (HANDLE) crtget_osfhandle (fd);
749-
} else {
750-
h = (HANDLE) crtget_osfhandle (posixFD);
751-
}
752-
753-
if( h == INVALID_HANDLE_VALUE) {
754-
errno = EBADF;
755-
return -1;
756-
}
757-
758-
l.QuadPart = length;
737+
if (posixFD != -1) {
738+
HANDLE h = (HANDLE) crtget_osfhandle(posixFD);
739+
if (h == INVALID_HANDLE_VALUE) {
740+
errno = EBADF;
741+
return -1;
742+
}
759743

760-
if (!SetFilePointerEx(h, l, &o, FILE_BEGIN)) return -1;
761-
if (!SetEndOfFile(h)) return -1;
744+
LARGE_INTEGER l, o;
745+
l.QuadPart = length;
762746

747+
if (!SetFilePointerEx(h, l, &o, FILE_BEGIN)) return -1;
748+
if (!SetEndOfFile(h)) return -1;
749+
}
763750
return 0;
764751
} CATCH_AND_REPORT();
765752

@@ -986,11 +973,29 @@ u_short redis_ntohs_impl(u_short netshort) {
986973
}
987974

988975
int redis_setmode_impl(int fd,int mode) {
989-
return crtsetmode(fd,mode);
976+
return crt_setmode(fd,mode);
990977
}
991978

992979
size_t redis_fwrite_impl(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
993-
return crtfwrite(_Str, _Size, _Count, _File);
980+
return crt_fwrite(_Str, _Size, _Count, _File);
981+
}
982+
983+
int redis_fclose_impl(FILE * file) {
984+
int posixFD = crt_fileno(file);
985+
if (posixFD != -1) {
986+
RFDMap::getInstance().removePosixFD(posixFD);
987+
}
988+
return crt_fclose(file);
989+
}
990+
991+
int redis_fileno_impl(FILE* file) {
992+
int rfd = -1;
993+
int posixFD = crt_fileno(file);
994+
if (posixFD != -1) {
995+
// if posixFD is already mapped, addPosixFD() will return the existing rfd.
996+
rfd = RFDMap::getInstance().addPosixFD(posixFD);
997+
}
998+
return rfd;
994999
}
9951000

9961001
auto f_select = dllfunctor_stdcall<int, int, fd_set*, fd_set*, fd_set*, const struct timeval*>("ws2_32.dll", "select");
@@ -1048,11 +1053,8 @@ int redis_access_impl(const char *pathname, int mode) {
10481053
u_int64 redis_lseek64_impl(int fd, u_int64 offset, int whence) {
10491054
try {
10501055
int posixFD = RFDMap::getInstance().lookupPosixFD(fd);
1051-
if( posixFD != -1) {
1056+
if (posixFD != -1) {
10521057
return crt_lseek64(posixFD, offset, whence);
1053-
} else {
1054-
errno = EBADF;
1055-
return 0;
10561058
}
10571059
} CATCH_AND_REPORT();
10581060

@@ -1063,11 +1065,8 @@ u_int64 redis_lseek64_impl(int fd, u_int64 offset, int whence) {
10631065
intptr_t redis_get_osfhandle_impl(int fd) {
10641066
try {
10651067
int posixFD = RFDMap::getInstance().lookupPosixFD(fd);
1066-
if( posixFD != -1) {
1068+
if (posixFD != -1) {
10671069
return crtget_osfhandle(posixFD);
1068-
} else {
1069-
errno = EBADF;
1070-
return 0;
10711070
}
10721071
} CATCH_AND_REPORT();
10731072

@@ -1191,6 +1190,8 @@ class Win32_FDSockMap {
11911190
gethostbyname = redis_gethostbyname_impl;
11921191
inet_ntoa = redis_inet_ntoa_impl;
11931192
fdapi_fwrite = redis_fwrite_impl;
1193+
fdapi_fclose = redis_fclose_impl;
1194+
fdapi_fileno = redis_fileno_impl;
11941195
fdapi_setmode = redis_setmode_impl;
11951196
WSASetLastError = redis_WSASetLastError_impl;
11961197
WSAGetLastError = redis_WSAGetLastError_impl;

src/Win32_Interop/Win32_FDAPI.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ typedef int (*redis_WSASocket)(int af, int type, int protocol, LPWSAPROTOCOL_INF
152152
// other API forwards
153153
typedef int (*redis_setmode)(int fd,int mode);
154154
typedef size_t (*redis_fwrite)(const void * _Str, size_t _Size, size_t _Count, FILE * _File);
155+
typedef int (*redis_fclose)(FILE* file);
156+
typedef int (*redis_fileno)(FILE* file);
155157

156158
// API prototypes must match the unix implementation
157159
typedef int (*redis_pipe)(int pipefd[2]);
@@ -237,6 +239,8 @@ extern redis_getsockname getsockname;
237239
extern redis_ntohs ntohs;
238240
extern redis_setmode fdapi_setmode;
239241
extern redis_fwrite fdapi_fwrite;
242+
extern redis_fclose fdapi_fclose;
243+
extern redis_fileno fdapi_fileno;
240244

241245
extern redis_select select;
242246
extern redis_ntohl ntohl;
@@ -267,6 +271,8 @@ int StorageSize(const SOCKADDR_STORAGE *ss);
267271
#define close(fd) fdapi_close(fd)
268272
#define setmode(fd,mode) fdapi_setmode(fd,mode)
269273
#define fwrite(Str, Size, Count, File) fdapi_fwrite(Str,Size,Count,File)
274+
#define fclose(File) fdapi_fclose(File)
275+
#define fileno(File) fdapi_fileno(File)
270276
#define _get_osfhandle(fd) fdapi_get_osfhandle(fd)
271277

272278
#define _INC_STAT_INL

src/Win32_Interop/Win32_fdapi_crt.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ intptr_t crtget_osfhandle(int fd) {
5252
return _get_osfhandle(fd);
5353
}
5454

55-
int crtsetmode(int fd, int mode) {
55+
int crt_setmode(int fd, int mode) {
5656
return ::_setmode(fd, mode);
5757
}
5858

59-
size_t crtfwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
59+
size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
6060
// 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,
6161
// 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
6262
// 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
63-
// impacts wirites that straddle page boundaries.
63+
// impacts writes that straddle page boundaries.
6464
const intptr_t pageSize = 4096;
6565
char* p = (char*)_Str;
6666
char* pageStart = p - ((intptr_t)p % pageSize);
@@ -74,6 +74,13 @@ size_t crtfwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
7474
return ::fwrite(_Str, _Size, _Count, _File);
7575
}
7676

77+
int crt_fclose(FILE* file) {
78+
return ::fclose(file);
79+
}
80+
81+
int crt_fileno(FILE* file) {
82+
return ::_fileno(file);
83+
}
7784

7885
int crt_isatty(int fd) {
7986
return _isatty(fd);

src/Win32_Interop/Win32_fdapi_crt.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ int crt_write(int fd, const void *buffer, unsigned int count);
3131
int crt_open(const char *filename, int oflag, int pmode);
3232
int crt_open_osfhandle(intptr_t osfhandle, int flags);
3333
intptr_t crtget_osfhandle(int fd);
34-
int crtsetmode(int fd, int mode);
35-
size_t crtfwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File);
34+
int crt_setmode(int fd, int mode);
35+
size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File);
36+
int crt_fclose(FILE* file);
37+
int crt_fileno(FILE* file);
3638
int crt_isatty(int fd);
3739
int crt_access(const char *pathname, int mode);
3840
__int64 crt_lseek64(int fd, __int64 offset, int origin);

src/Win32_Interop/win32_rfdmap.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ RFDMap& RFDMap::getInstance() {
3131

3232
RFDMap::RFDMap() {
3333
InitializeCriticalSection(&mutex);
34-
maxRFD = minRFD;
34+
// stdin, assigned rfd = 0
35+
addPosixFD(0);
36+
// stdout, assigned rfd = 1
37+
addPosixFD(1);
38+
// stderr, assigned rfd = 2
39+
addPosixFD(2);
3540
}
3641

3742
RFD RFDMap::getNextRFDAvailable() {
@@ -41,8 +46,7 @@ RFD RFDMap::getNextRFDAvailable() {
4146
rfd = RFDRecyclePool.front();
4247
RFDRecyclePool.pop();
4348
} else {
44-
maxRFD = minRFD + (int) SocketToRFDMap.size() + (int) PosixFDToRFDMap.size();
45-
rfd = maxRFD;
49+
rfd = (int) SocketToRFDMap.size() + (int) PosixFDToRFDMap.size();
4650
}
4751
LeaveCriticalSection(&mutex);
4852
return rfd;
@@ -78,7 +82,7 @@ RFD RFDMap::addPosixFD(int posixFD) {
7882
RFD rfd;
7983
EnterCriticalSection(&mutex);
8084
if (PosixFDToRFDMap.find(posixFD) != PosixFDToRFDMap.end()) {
81-
rfd = invalidRFD;
85+
rfd = PosixFDToRFDMap[posixFD];
8286
} else {
8387
rfd = getNextRFDAvailable();
8488
PosixFDToRFDMap[posixFD] = rfd;
@@ -89,15 +93,19 @@ RFD RFDMap::addPosixFD(int posixFD) {
8993
}
9094

9195
void RFDMap::removePosixFD(int posixFD) {
92-
EnterCriticalSection(&mutex);
93-
PosixFD2RFDIterator mit = PosixFDToRFDMap.find(posixFD);
94-
if (mit != PosixFDToRFDMap.end()) {
95-
RFD rfd = (*mit).second;
96-
RFDRecyclePool.push(rfd);
97-
RFDToPosixFDMap.erase(rfd);
98-
PosixFDToRFDMap.erase(posixFD);
96+
// posixFD between 0 and 2 should never be removed since they are assigned
97+
// to stdin, stdout and stderr
98+
if (posixFD > 2) {
99+
EnterCriticalSection(&mutex);
100+
PosixFD2RFDIterator mit = PosixFDToRFDMap.find(posixFD);
101+
if (mit != PosixFDToRFDMap.end()) {
102+
RFD rfd = (*mit).second;
103+
RFDRecyclePool.push(rfd);
104+
RFDToPosixFDMap.erase(rfd);
105+
PosixFDToRFDMap.erase(posixFD);
106+
}
107+
LeaveCriticalSection(&mutex);
99108
}
100-
LeaveCriticalSection(&mutex);
101109
}
102110

103111
SOCKET RFDMap::lookupSocket(RFD rfd) {

src/Win32_Interop/win32_rfdmap.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ class RFDMap {
7878
RFDRecyclePoolType RFDRecyclePool;
7979

8080
private:
81-
const static int minRFD = 3; // 0, 1 and 2 are reserved for stdin, stdout and stderr
82-
RFD maxRFD;
8381
CRITICAL_SECTION mutex;
8482

8583
public:

0 commit comments

Comments
 (0)