Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 6ae4ced

Browse files
vtjnashsaghul
authored andcommitted
LEP-005: Use Windows HANDLEs not fds
1 parent 9be2641 commit 6ae4ced

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

000-index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Approved
44

55
* [003-create-sockets-early](https://github.com/libuv/leps/blob/master/003-create-sockets-early.md)
6+
* [005-windows-handles-not-fd](https://github.com/libuv/leps/blob/master/005-windows-handles-not-fd.md)
67

78

89
## Rejected

005-windows-handles-not-fd.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
| Title | Windows HANDLEs not fds |
2+
|--------|-------------------------|
3+
| Author | @vtjnash |
4+
| Status | ACCEPTED |
5+
| Date | 2017-03-23 |
6+
7+
8+
## Overview
9+
10+
Currently the libuv API requires passing in a MSVCRT-emulated file-descriptor,
11+
and then immediately discards the wrapper and uses the native HANDLE instead.
12+
This LEP proposes is to consistently remove this extra indirection from all APIs in libuv,
13+
and replace all usages of `uv_os_sock_t` and `uv_file`, with `uv_os_fd_t`.
14+
On Unix systems, this would be a `int fd` while on Windows it would be a `void* HANDLE`.
15+
16+
## Details
17+
18+
Original issue: [https://github.com/libuv/libuv/issues/856]()
19+
20+
On Windows, a file descriptor is emulated in user-space as a wrapper around the real Win32 API.
21+
Indeed, the first operation libuv almost always must do is to throw away the wrapper (by calling `uv__get_osfhandle`).
22+
However, since the wrapper is implemented in user-space, this adds unnecessary overhead,
23+
makes the API less flexible, and is potentially error-prone
24+
(it assumes that the caller and libuv are linking against the same copy of msvcrt).
25+
A couple of functions already accept a `uv_os_sock_t`, essentially just to work around these limitations.
26+
This change would mean libuv no longer needs to add duplicate APIs for every constructor
27+
(e.g. see `uv_poll_init` vs. `uv_poll_init_socket`).
28+
29+
The limitations of the current API include:
30+
31+
- Assumes the caller is linked against the same copy of msvcrt
32+
- Artificial limits the maximum number of open handles to 2048
33+
- The behavior is undefined when called from a GUI program [https://support.microsoft.com/en-us/kb/105305]()
34+
- Some useful APIs (such as `pipe`) aren't emulated by msvcrt.
35+
- Requires allocation of the POSIX-compatibility wrapper (wastes memory and could fail)
36+
37+
38+
## Implementation
39+
40+
The `uv_file` typedef would be deleted and replaced by `uv_os_fd_t` uniformly across all APIs.
41+
This has minor code change implications for consumers of the libuv API (see the Transition section below).
42+
But only cosmetic changes to the internal implementation of libuv,
43+
and is invisible to external customers of libuv-based programs (such as child processes).
44+
45+
The `uv_spawn` implementation would be fixed to declare `fd` as a `uv_os_fd_t` instead of a `int`
46+
in `uv_stdio_container_t.data`.
47+
48+
The `uv__get_osfhandle` translation code would be deleted from everywhere.
49+
50+
Addtionally, constants such as `UV_STDIN_FD` would be provided to provide cross-platform
51+
reference to the standard constants for stdio:
52+
on Unix these are 0, 1, 2; on Windows these are -10, -11, -12.
53+
54+
The APIs this change affects are:
55+
- uv_tty_init
56+
- uv_guess_handle
57+
- uv_pipe_open
58+
- uv_poll_init / uv_poll_init_socket (merged)
59+
- uv_fs_close
60+
- uv_fs_read
61+
- uv_fs_write
62+
- uv_fs_fstat
63+
- uv_fs_fsync
64+
- uv_fs_fdatasync
65+
- uv_fs_ftruncate
66+
- uv_fs_sendfile
67+
- uv_fs_futime
68+
- uv_fs_fchmod
69+
- uv_fs_fchown
70+
71+
## Transition
72+
73+
Existing clients can initially transition to the new API by using the following helper function code snippet
74+
(which would be added verbatim to uv.h):
75+
76+
#ifdef _WIN32
77+
78+
79+
static inline HANDLE uv_get_osfhandle(int fd) {
80+
return _get_osfhandle(fd);
81+
}
82+
83+
84+
static inline HANDLE uv_convert_fd_to_handle(int fd) {
85+
HANDLE new_handle;
86+
if (uv__duplicate_handle(NULL, uv_get_osfhandle(fd), &new_handle))
87+
return INVALID_HANDLE_VALUE;
88+
_close(fd);
89+
return new_handle;
90+
}
91+
92+
93+
#else
94+
95+
96+
static inline int uv_get_osfhandle(int fd) {
97+
return fd;
98+
}
99+
100+
101+
static inline int uv_convert_fd_to_handle(int fd) {
102+
return fd;
103+
}
104+
105+
106+
#endif
107+
108+
Longer term, those clients would now be able to transition to using the Win32 API directly
109+
instead of requiring indirection through the MSVCRT API.
110+
111+
## Resolution
112+
113+
This LEP is ACCEPTED and implemented in https://github.com/libuv/libuv/pull/1166

0 commit comments

Comments
 (0)