-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LEP-0005 implementation – remove uv_file #1166
Conversation
It's not clear to me why you removed uv_poll_init(). It's used a lot, removing it is rather disruptive. |
On Windows, it's an alias for |
I'd rather keep |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made a first review round! I'm happy with the code reduction and how fs operations are simpler :-)
I left a bunch of comments but nothing major. Please address them, rebase and I'll kick off a CI run and give it another review round.
include/uv.h
Outdated
@@ -431,10 +427,56 @@ UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); | |||
UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value); | |||
|
|||
UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd); | |||
UV_EXTERN int uv_dup(uv_os_fd_t fd, uv_os_fd_t* dup); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you rename the parameter to dupfd
include/uv.h
Outdated
#endif | ||
|
||
INLINE static uv_os_fd_t uv_get_osfhandle(int fd) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: brace on the previous line
include/uv.h
Outdated
{ | ||
#ifdef _WIN32 | ||
/* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */ | ||
/* So if you plan on using invalid fd, you will need to install a _CrtSetReportHook handler */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make this a block comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have that handler added automaticaly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, libuv can't add that handler automatically as the _CrtSetReportHook
may be non-unique in the process. Since libuv won't use file-descriptors after this change, it'll never see an invalid one.
include/uv.h
Outdated
|
||
|
||
INLINE static uv_os_fd_t uv_convert_fd_to_handle(int fd) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: braces
include/uv.h
Outdated
# define INLINE inline | ||
#endif | ||
|
||
INLINE static uv_os_fd_t uv_get_osfhandle(int fd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please define these in uv-common.c, no need to inline them, IMHO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inlining them is the only way to get the linker to point to the right copy of this function.
result = -1; | ||
break; | ||
} | ||
/* hopefully n == n_out here (e.g. that fd_out wasn't opened non-blocking mode) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we account for the case where that doesn't happen? if the answer it's "never", place an assert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just documenting an existing potential deficiency (_write
is just a thin wrapper for WriteFile
, although I shudder to think of what this code used to do if someone accidentally opened a fd with _O_TEXT
). I don't think anyone is passing in a pipe opened in non-blocking mode intentionally.
} else { | ||
fs__open(req); | ||
return req->result; | ||
if (req->result < 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the previous version was more readable, please revert this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old version does a silent truncating cast (from HANDLE to int), #1166 (comment)
src/win/process-stdio.c
Outdated
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { | ||
/* If fdopt.data.file is pointing at one of the pseudo stdio handles, | ||
* but it is not valid ignore the error. */ | ||
if ((fdopt.data.file == UV_STDIN_FD || fdopt.data.file == UV_STDOUT_FD || fdopt.data.file == UV_STDERR_FD) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: long line
src/win/tty.c
Outdated
*/ | ||
handle = GetStdHandle((DWORD)(uintptr_t) handle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this construct seems to repeat a bit, maybe create an internal uv__dup_stdio_handle
helper?
@@ -376,7 +376,8 @@ int run_ipc_send_recv_helper(uv_loop_t* loop, int inprocess) { | |||
r = uv_listen((uv_stream_t*)&ctx2.listen, SOMAXCONN, listen_cb); | |||
ASSERT(r == 0); | |||
} else { | |||
r = uv_pipe_open(&ctx2.channel, 0); | |||
uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't UV_STDIN_FD work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would work, since for the purposes of this test harness they happen to get set to the same stream. However, testing with fd = 0
is slightly more accurate – and makes for better example code for the expected nodejs usage.
39203ac
to
94707fd
Compare
I've updated the PR based on your review feedback. Let me know what else needs to be done here. |
Hey @vtjnash I'm ready to land this, once we have a bit of documentation. I seem to have forgotten to point that out earlier, sorry about that. We need:
|
Thanks @sagful. I had documentation update in my TODO list at the top, and was just waiting for the LEP to be merged. I also added the migration guide – thanks for mentioned that too. Let me know if it looks good (or has any typos :P). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more documentation fixes are required. Also please drop the public uv_dup.
docs/src/handle.rst
Outdated
@@ -179,6 +179,12 @@ just for some handle types. | |||
Be very careful when using this function. libuv assumes it's in control of the file | |||
descriptor so any change to it may lead to malfunction. | |||
|
|||
.. c:function:: int uv_dup(uv_os_fd_t fd, uv_os_fd_t* dupfd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see we only use this internally, please make it private.
|
||
Destructively converts a file descriptor in the C runtime | ||
to the OS-dependent handle. | ||
Upon return, the input ``fd`` parameter is invalid and closed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add some more details mentioning this only makes sense on windows, what function uses internally, etc.
@@ -161,7 +161,7 @@ API | |||
Cleanup request. Must be called after a request is finished to deallocate | |||
any memory libuv might have allocated. | |||
|
|||
.. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) | |||
.. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t file, uv_fs_cb cb) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a .. versionchanged::
for each of these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should that be v2.0.0, or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a fixup!
commit to address the doc comments, assuming for now that I should go with v2.0.0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that's the one, thanks!
Constants ``UV_STDIN_FD``, ``UV_STDOUT_FD``, and ``UV_STDERR_FD`` provide cross-platform | ||
references to the standard constants for stdio access, and can be used in place of any ``uv_os_fd_t``. | ||
Existing clients can transition to the new API by using the conversion function ``uv_convert_fd_to_handle`` | ||
defined in the libuv header file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please expand a bit here: show an example on how one would open stdin before and how to do it now.
include/uv.h
Outdated
# define INLINE inline | ||
#endif | ||
|
||
INLINE static uv_os_fd_t uv_get_osfhandle(int fd) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please move these to uv-common. We tend not to have implementations in uv.h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These need to be statically linked into the caller, which is why they can't go in the libuv library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recently opened issue #1291 demonstrates why it is required that this code be part of the header and not the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see! Can you please add a comment so someone doesn't f*ck this up in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, added.
Damn, GH doesn't send notifications when you add new commits so I missed this. I'll review today @vtjnash. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM once uv_dup is removed from the public API. That's the only thing left, fantastic work here!
Ok, I added a commit to remove |
bump. |
All comments have been addressed, should be ready to merge. |
Thanks - looks like I need to add the io.h header. |
The uv__get_osfhandle() function is a private functio of the Windows subsystem, and its used to get a Windows HANDLE out of a file descriptor number. The motivation behind making this function public is to allow Node.js programs to pass file descriptors created using fs.open() to native Node.js C++ add-ons, and be able to successfully convert them to Windows HANDLEs. Refs: #1166 Refs: nodejs/node#6369 Fixes: #1291 PR-URL: #1323 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Since on Windows, HANDLEs are not the same as file descriptors, confusing the two meant that almost all APIs in libuv had to go through a thin compatibility layer, adding needless complication. This removes that layer of external indirection and instead works with the native Win32 API directly.
Alright, I've tried to cleanup the list of headers affected by this change to help avoid accidentally referencing shared state in msvcrt.dll where not intended. I think this should address the CI test failure, but would be best to re-run that to check that I didn't miss any. |
💚 landing! |
Since on Windows HANDLEs are not the same as file descriptors, confusing the two meant that almost all APIs in libuv had to go through a thin compatibility layer, adding needless complication. This removes that layer of external indirection and instead works with the native Win32 API directly. See: https://github.com/libuv/leps/blob/master/005-windows-handles-not-fd.md PR-URL: #1166 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
@libuv/collaborators I'll try to merge v1.x into master this weekend. It will be a messy one after this commit, but once done the next ones should be easier. |
😀😀😀💥💥💥Thanks! |
It was already wrong inside libuv#974 (`UV_EINVAL` and `-EINVAL` are different on Windows), but libuv#1166 made it even worse. It's now wrong on windows and *nix 😆
It was already wrong inside libuv#974 (`UV_EINVAL` and `-EINVAL` are different on Windows), but libuv#1166 made it even worse. It's now wrong on windows and *nix 😆
Since on Windows, HANDLEs are not the same as file descriptors,
confusing the two meant that almost all APIs in libuv had to go through
a thin compatibility layer, adding needless complication.
This removes that layer of external indirection and instead
works with the native Win32 API directly.
This is the implementation for libuv/leps#8 which closes #856.
APIs added:
uv_get_osfhandle
uv_convert_fd_to_handle
uv_dup
UV_STDIN_FD
/UV_STDOUT_FD
/UV_STDERR_FD
APIs removed:
uv_poll_init_socket
(now identical touv_poll_init
)TODO list: