Skip to content
This repository was archived by the owner on May 4, 2018. It is now read-only.

unix, windows: add uv_fileno #1435

Merged
merged 2 commits into from
Aug 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-getaddrinfo.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-handle-fileno.c \
test/test-hrtime.c \
test/test-idle.c \
test/test-ip4-addr.c \
Expand Down
1 change: 1 addition & 0 deletions include/uv-unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ typedef struct uv_buf_t {

typedef int uv_file;
typedef int uv_os_sock_t;
typedef int uv_os_fd_t;

#define UV_ONCE_INIT PTHREAD_ONCE_INIT

Expand Down
2 changes: 1 addition & 1 deletion include/uv-win.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ typedef struct uv_buf_t {
} uv_buf_t;

typedef int uv_file;

typedef SOCKET uv_os_sock_t;
typedef HANDLE uv_os_fd_t;

typedef HANDLE uv_thread_t;

Expand Down
2 changes: 2 additions & 0 deletions include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,8 @@ UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
*/
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);

/*
* Returns or sets the size of the send buffer that the operating
* system uses for the socket.
Expand Down
30 changes: 30 additions & 0 deletions src/unix/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,36 @@ void uv_disable_stdio_inheritance(void) {
}


int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
int fd_out;

switch (handle->type) {
case UV_TCP:
case UV_NAMED_PIPE:
case UV_TTY:
fd_out = uv__stream_fd((uv_stream_t*) handle);
break;

case UV_UDP:
fd_out = ((uv_udp_t *) handle)->io_watcher.fd;
break;

case UV_POLL:
fd_out = ((uv_poll_t *) handle)->io_watcher.fd;
break;

default:
return -EINVAL;
}

if (uv__is_closing(handle) || fd_out == -1)
return -EBADF;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's kind of bad style to return an error code but still mutate the out parameter, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True that, will fix.


*fd = fd_out;
return 0;
}


static void uv__run_pending(uv_loop_t* loop) {
QUEUE* q;
uv__io_t* w;
Expand Down
37 changes: 37 additions & 0 deletions src/win/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,43 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
return r;
}


int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
uv_os_fd_t fd_out;

switch (handle->type) {
case UV_TCP:
fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket;
break;

case UV_NAMED_PIPE:
fd_out = ((uv_pipe_t*) handle)->handle;
break;

case UV_TTY:
fd_out = ((uv_tty_t*) handle)->handle;
break;

case UV_UDP:
fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket;
break;

case UV_POLL:
fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket;
break;

default:
return UV_EINVAL;
}

if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE)
return UV_EBADF;

*fd = fd_out;
return 0;
}


int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
int r;
int len;
Expand Down
2 changes: 2 additions & 0 deletions src/win/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {

if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
closesocket(handle->socket);
handle->socket = INVALID_SOCKET;
handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
}

Expand Down Expand Up @@ -1368,6 +1369,7 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {

if (close_socket) {
closesocket(tcp->socket);
tcp->socket = INVALID_SOCKET;
tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
}

Expand Down
1 change: 1 addition & 0 deletions src/win/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,7 @@ void uv_tty_close(uv_tty_t* handle) {
if (handle->flags & UV_HANDLE_READING)
uv_tty_read_stop(handle);

handle->handle = INVALID_HANDLE_VALUE;
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
uv__handle_closing(handle);

Expand Down
1 change: 1 addition & 0 deletions src/win/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
uv_udp_recv_stop(handle);
closesocket(handle->socket);
handle->socket = INVALID_SOCKET;

uv__handle_closing(handle);

Expand Down
120 changes: 120 additions & 0 deletions test/test-handle-fileno.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include "uv.h"
#include "task.h"


static int get_tty_fd(void) {
/* Make sure we have an FD that refers to a tty */
#ifdef _WIN32
HANDLE handle;
handle = CreateFileA("conout$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
return -1;
return _open_osfhandle((intptr_t) handle, 0);
#else /* unix */
return open("/dev/tty", O_RDONLY, 0);
#endif
}


TEST_IMPL(handle_fileno) {
int r;
int tty_fd;
struct sockaddr_in addr;
uv_os_fd_t fd;
uv_tcp_t tcp;
uv_udp_t udp;
uv_pipe_t pipe;
uv_tty_t tty;
uv_idle_t idle;
uv_loop_t* loop;

loop = uv_default_loop();
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));

r = uv_idle_init(loop, &idle);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &idle, &fd);
ASSERT(r == UV_EINVAL);
uv_close((uv_handle_t*) &idle, NULL);

r = uv_tcp_init(loop, &tcp);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &tcp, &fd);
ASSERT(r == UV_EBADF);
r = uv_tcp_bind(&tcp, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &tcp, &fd);
ASSERT(r == 0);
uv_close((uv_handle_t*) &tcp, NULL);
r = uv_fileno((uv_handle_t*) &tcp, &fd);
ASSERT(r == UV_EBADF);

r = uv_udp_init(loop, &udp);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &udp, &fd);
ASSERT(r == UV_EBADF);
r = uv_udp_bind(&udp, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &udp, &fd);
ASSERT(r == 0);
uv_close((uv_handle_t*) &udp, NULL);
r = uv_fileno((uv_handle_t*) &udp, &fd);
ASSERT(r == UV_EBADF);

r = uv_pipe_init(loop, &pipe, 0);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &pipe, &fd);
ASSERT(r == UV_EBADF);
r = uv_pipe_bind(&pipe, TEST_PIPENAME);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &pipe, &fd);
ASSERT(r == 0);
uv_close((uv_handle_t*) &pipe, NULL);
r = uv_fileno((uv_handle_t*) &pipe, &fd);
ASSERT(r == UV_EBADF);

tty_fd = get_tty_fd();
if (tty_fd < 0) {
LOGF("Cannot open a TTY fd");
} else {
r = uv_tty_init(loop, &tty, tty_fd, 0);
ASSERT(r == 0);
r = uv_fileno((uv_handle_t*) &tty, &fd);
ASSERT(r == 0);
uv_close((uv_handle_t*) &tty, NULL);
r = uv_fileno((uv_handle_t*) &tty, &fd);
ASSERT(r == UV_EBADF);
}

uv_run(loop, UV_RUN_DEFAULT);

MAKE_VALGRIND_HAPPY();
return 0;
}
3 changes: 3 additions & 0 deletions test/test-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ TEST_DECLARE (get_currentexe)
TEST_DECLARE (process_title)
TEST_DECLARE (cwd_and_chdir)
TEST_DECLARE (get_memory)
TEST_DECLARE (handle_fileno)
TEST_DECLARE (hrtime)
TEST_DECLARE (getaddrinfo_fail)
TEST_DECLARE (getaddrinfo_basic)
Expand Down Expand Up @@ -503,6 +504,8 @@ TASK_LIST_START

TEST_ENTRY (get_loadavg)

TEST_ENTRY (handle_fileno)

TEST_ENTRY (hrtime)

TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
Expand Down
1 change: 1 addition & 0 deletions uv.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@
'test/test-getaddrinfo.c',
'test/test-getnameinfo.c',
'test/test-getsockname.c',
'test/test-handle-fileno.c',
'test/test-hrtime.c',
'test/test-idle.c',
'test/test-ip6-addr.c',
Expand Down