Skip to content

Commit

Permalink
Declare UCRT posix functions
Browse files Browse the repository at this point in the history
Summary:
This changes `folly/portability/Windows.h` so that the posix functions in the Microsoft Windows Universal C Runtime (UCRT) are declared. Before this change `folly/portability/Windows.h` would include `windows.h` from the UCRT so that its posix functions would **not** be declared and they would instead be declared by headers in `folly/portability`.

Now folly only declares posix functions missing from the Windows SDK (e.g., `sysconf`). Folly's posix functions that have the same behavior as the ones the UCRT are removed.

Removed declarations:
- creat
- open
- mktemp
- chmod
- umask
- access
- chdir
- close
- dup
- dup2
- getcwd
- isatty
- lseek
- read
- rmdir
- pipe
- write

This is the 3rd phase in a 3-phase change to remove folly's global definitions of the posix functions that conflict with windows CRT.
The 1st phase created namespaces for folly's posix functions. The 2nd phase updates callsites to use the qualified name of folly's  `open`, `close`, `read`, `write`, and `pipe`  functions. The 3rd and final phase removes folly's globally defined posix functions and have windows CRT define them again.

**What is the reason for this change?**
Folly's global definitions of posix functions on Windows causes `#include` order issues if folly is not included first.

For example, when `gtest/gtest.h` is included before folly, gtest includes `windows.h` and that declares `open`, `read`, and `chdir`, which creates ambiguous references to folly's `open`, `read`, and `chdir`.

Another example is where posix functions go undeclared when `folly/portability/windows.h` is included without other portability headers (e.g., `folly/portability/unistd.h`). `folly/portability/windows.h` includes `windows.h` in a way that only underscore versions of the posix functions are available (e.g., `_open`, `_close`).

These issues create friction for windows development.

**Background: What is the purpose of `folly::portability::{fcntl,stdlib,sysstat,unistd}`?**
It is a portability layer to make posix functions available and behave consistently across platforms. Some posix functions don't exist on windows (e.g., `sysconf`). Some other posix functions, folly changes to adapt behavior across platforms. For example, on windows folly defines `open`, `read`, `write`, and `close` functions to work with sockets. Folly makes these functions available in the global scope for convenience.

Reviewed By: Orvid

Differential Revision: D65255065

fbshipit-source-id: f47f0768e56f1e6f185f07458c5a443ed485a75f
  • Loading branch information
skrueger authored and facebook-github-bot committed Nov 25, 2024
1 parent d2265fd commit 974ac40
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 126 deletions.
22 changes: 10 additions & 12 deletions third-party/folly/src/folly/portability/Fcntl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
namespace folly {
namespace portability {
namespace fcntl {
int creat(char const* fn, int pm) {
return _creat(fn, pm);
}

int fcntl(int fd, int cmd, ...) {
va_list args;
int res = -1;
Expand Down Expand Up @@ -85,6 +81,15 @@ int fcntl(int fd, int cmd, ...) {
return res;
}

int posix_fallocate(int fd, off_t offset, off_t len) {
// We'll pretend we always have enough space. We
// can't exactly pre-allocate on windows anyways.
return 0;
}
} // namespace fcntl
} // namespace portability

namespace fileops {
int open(char const* fn, int of, int pm) {
int fh;
int realMode = _S_IREAD;
Expand All @@ -108,13 +113,6 @@ int open(char const* fn, int of, int pm) {
errno_t res = _sopen_s(&fh, fn, of, _SH_DENYNO, realMode);
return res ? -1 : fh;
}

int posix_fallocate(int fd, off_t offset, off_t len) {
// We'll pretend we always have enough space. We
// can't exactly pre-allocate on windows anyways.
return 0;
}
} // namespace fcntl
} // namespace portability
} // namespace fileops
} // namespace folly
#endif
4 changes: 1 addition & 3 deletions third-party/folly/src/folly/portability/Fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@
namespace folly {
namespace portability {
namespace fcntl {
int creat(char const* fn, int pm);
int fcntl(int fd, int cmd, ...);
int posix_fallocate(int fd, off_t offset, off_t len);
int open(char const* fn, int of, int pm = 0);
} // namespace fcntl
} // namespace portability
} // namespace folly
Expand All @@ -69,7 +67,7 @@ FOLLY_POP_WARNING
namespace folly {
namespace fileops {
#ifdef _WIN32
using portability::fcntl::open;
int open(char const* fn, int of, int pm = 0);
#else
using ::open;
#endif
Expand Down
1 change: 0 additions & 1 deletion third-party/folly/src/folly/portability/Stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ int clearenv();
#endif

#ifdef _WIN32
char* mktemp(char* tn);
char* mkdtemp(char* tn);
int mkstemp(char* tn);
char* realpath(const char* path, char* resolved_path);
Expand Down
8 changes: 0 additions & 8 deletions third-party/folly/src/folly/portability/SysStat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
namespace folly {
namespace portability {
namespace sysstat {
int chmod(char const* fn, int am) {
return _chmod(fn, am);
}

int fchmod(int fd, mode_t mode) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
Expand Down Expand Up @@ -60,10 +56,6 @@ int lstat(const char* path, struct stat* st) {
int mkdir(const char* fn, int /* mode */) {
return _mkdir(fn);
}

int umask(int md) {
return _umask(md);
}
} // namespace sysstat
} // namespace portability
} // namespace folly
Expand Down
2 changes: 0 additions & 2 deletions third-party/folly/src/folly/portability/SysStat.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@
namespace folly {
namespace portability {
namespace sysstat {
int chmod(char const* fn, int am);
int fchmod(int fd, mode_t mode);
int lstat(const char* path, struct stat* st);
int mkdir(const char* fn, int mode);
int umask(int md);
} // namespace sysstat
} // namespace portability
} // namespace folly
Expand Down
106 changes: 38 additions & 68 deletions third-party/folly/src/folly/portability/Unistd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,29 +198,6 @@ ProcessHandleWrapper getParentProcessHandle() {
}
} // namespace

int access(char const* fn, int am) {
return _access(fn, am);
}

int chdir(const char* path) {
return _chdir(path);
}

int close(int fh) {
if (folly::portability::sockets::is_fh_socket(fh)) {
return netops::detail::SocketFileDescriptorMap::close(fh);
}
return _close(fh);
}

int dup(int fh) {
return _dup(fh);
}

int dup2(int fhs, int fhd) {
return _dup2(fhs, fhd);
}

int fsync(int fd) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
Expand Down Expand Up @@ -254,10 +231,6 @@ int ftruncate(int fd, off_t len) {
return 0;
}

char* getcwd(char* buf, int sz) {
return _getcwd(buf, sz);
}

int getdtablesize() {
return _getmaxstdio();
}
Expand All @@ -278,32 +251,14 @@ uid_t getuid() {
return 1;
}

int isatty(int fh) {
return _isatty(fh);
}

int lockf(int fd, int cmd, off_t len) {
return _locking(fd, cmd, len);
}

off_t lseek(int fh, off_t off, int orig) {
return _lseek(fh, off, orig);
}

off64_t lseek64(int fh, off64_t off, int orig) {
return _lseeki64(fh, static_cast<int64_t>(off), orig);
}

int rmdir(const char* path) {
return _rmdir(path);
}

int pipe(int pth[2]) {
// We need to be able to listen to pipes with
// libevent, so they need to be actual sockets.
return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
}

ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
const bool is64Bit = false;
return wrapPositional<is64Bit>(_read, fd, offset, buf, (unsigned int)count);
Expand All @@ -319,27 +274,6 @@ ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
return wrapPositional<is64Bit>(_write, fd, offset, buf, (unsigned int)count);
}

ssize_t read(int fh, void* buf, size_t count) {
if (folly::portability::sockets::is_fh_socket(fh)) {
SOCKET s = (SOCKET)_get_osfhandle(fh);
if (s != INVALID_SOCKET) {
auto r = folly::portability::sockets::recv(fh, buf, count, 0);
if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
errno = EAGAIN;
}
return r;
}
}
auto r = _read(fh, buf, static_cast<unsigned int>(count));
if (r == -1 && GetLastError() == ERROR_NO_DATA) {
// This only happens if the file was non-blocking and
// no data was present. We have to translate the error
// to a form that the rest of the world is expecting.
errno = EAGAIN;
}
return r;
}

ssize_t readlink(const char* path, char* buf, size_t buflen) {
if (!buflen) {
return -1;
Expand Down Expand Up @@ -411,6 +345,43 @@ int usleep(unsigned int ms) {
Sleep((DWORD)(ms / 1000));
return 0;
}
} // namespace unistd
} // namespace portability

namespace fileops {
int close(int fh) {
if (folly::portability::sockets::is_fh_socket(fh)) {
return netops::detail::SocketFileDescriptorMap::close(fh);
}
return _close(fh);
}

ssize_t read(int fh, void* buf, size_t count) {
if (folly::portability::sockets::is_fh_socket(fh)) {
SOCKET s = (SOCKET)_get_osfhandle(fh);
if (s != INVALID_SOCKET) {
auto r = folly::portability::sockets::recv(fh, buf, count, 0);
if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
errno = EAGAIN;
}
return r;
}
}
auto r = _read(fh, buf, static_cast<unsigned int>(count));
if (r == -1 && GetLastError() == ERROR_NO_DATA) {
// This only happens if the file was non-blocking and
// no data was present. We have to translate the error
// to a form that the rest of the world is expecting.
errno = EAGAIN;
}
return r;
}

int pipe(int pth[2]) {
// We need to be able to listen to pipes with
// libevent, so they need to be actual sockets.
return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
}

ssize_t write(int fh, void const* buf, size_t count) {
if (folly::portability::sockets::is_fh_socket(fh)) {
Expand Down Expand Up @@ -443,8 +414,7 @@ ssize_t write(int fh, void const* buf, size_t count) {
}
return r;
}
} // namespace unistd
} // namespace portability
} // namespace fileops
} // namespace folly

#endif
20 changes: 4 additions & 16 deletions third-party/folly/src/folly/portability/Unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,14 @@ namespace folly {
namespace portability {
namespace unistd {
using off64_t = int64_t;
int access(char const* fn, int am);
int chdir(const char* path);
int close(int fh);
int dup(int fh);
int dup2(int fhs, int fhd);
int fsync(int fd);
int ftruncate(int fd, off_t len);
char* getcwd(char* buf, int sz);
int getdtablesize();
int getgid();
pid_t getppid();
int getuid();
int isatty(int fh);
int lockf(int fd, int cmd, off_t len);
off_t lseek(int fh, off_t off, int orig);
off64_t lseek64(int fh, off64_t off, int orig);
ssize_t read(int fh, void* buf, size_t mcc);
int rmdir(const char* path);
int pipe(int pth[2]);
ssize_t pread(int fd, void* buf, size_t count, off_t offset);
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset);
ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset);
Expand All @@ -99,7 +88,6 @@ unsigned int sleep(unsigned int seconds);
long sysconf(int tp);
int truncate(const char* path, off_t len);
int usleep(unsigned int ms);
ssize_t write(int fh, void const* buf, size_t count);
} // namespace unistd
} // namespace portability
} // namespace folly
Expand All @@ -113,10 +101,10 @@ FOLLY_POP_WARNING
namespace folly {
namespace fileops {
#ifdef _WIN32
using folly::portability::unistd::close;
using folly::portability::unistd::pipe;
using folly::portability::unistd::read;
using folly::portability::unistd::write;
int close(int fh);
ssize_t read(int fh, void* buf, size_t mcc);
int pipe(int pth[2]);
ssize_t write(int fh, void const* buf, size_t count);
#else
using ::close;
using ::pipe;
Expand Down
16 changes: 0 additions & 16 deletions third-party/folly/src/folly/portability/Windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,8 @@
// disabled to ensure all of the normal names get declared properly.
#include <stdio.h>

#ifndef __STDC__
/* nolint */
#define __STDC__ 1
#pragma push_macro("_CRT_DECLARE_NONSTDC_NAMES")
#ifdef _CRT_DECLARE_NONSTDC_NAMES
#undef _CRT_DECLARE_NONSTDC_NAMES
#endif
#pragma push_macro("_CRT_INTERNAL_NONSTDC_NAMES")
#undef _CRT_INTERNAL_NONSTDC_NAMES
#include <direct.h> // @manual nolint
#include <io.h> // @manual nolint
#undef __STDC__
#pragma pop_macro("_CRT_INTERNAL_NONSTDC_NAMES")
#pragma pop_macro("_CRT_DECLARE_NONSTDC_NAMES")
#else
#include <direct.h> // @manual nolint
#include <io.h> // @manual nolint
#endif

#if defined(min) || defined(max)
#error Windows.h needs to be included by this header, or else NOMINMAX needs \
Expand Down

0 comments on commit 974ac40

Please sign in to comment.