Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/v1.x' into v1.x
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTechsTech committed Sep 12, 2024
2 parents a2b33b5 + a49f264 commit 06bab9c
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/unix/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
break;

case UV_TTY:
uv__stream_close((uv_stream_t*)handle);
uv__tty_close((uv_tty_t*)handle);
break;

case UV_TCP:
Expand Down
3 changes: 3 additions & 0 deletions src/unix/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
int uv__tcp_nodelay(int fd, int on);
int uv__tcp_keepalive(int fd, int on, unsigned int delay);

/* tty */
void uv__tty_close(uv_tty_t* handle);

/* pipe */
int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);

Expand Down
33 changes: 33 additions & 0 deletions src/unix/kqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@ int uv__io_fork(uv_loop_t* loop) {
int uv__io_check_fd(uv_loop_t* loop, int fd) {
struct kevent ev;
int rc;
struct stat sb;
#ifdef __APPLE__
char path[MAXPATHLEN];
#endif

if (uv__fstat(fd, &sb))
return UV__ERR(errno);

/* On FreeBSD, kqueue only supports EVFILT_READ notification for regular files
* and always reports ready events for writing, resulting in busy-looping.
*
* On Darwin, DragonFlyBSD, NetBSD and OpenBSD, kqueue reports ready events for
* regular files as readable and writable only once, acting like an EV_ONESHOT.
*
* Neither of the above cases should be added to the kqueue.
*/
if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
return UV_EINVAL;

#ifdef __APPLE__
/* On Darwin (both macOS and iOS), in addition to regular files, FIFOs also don't
* work properly with kqueue: the disconnection from the last writer won't trigger
* an event for kqueue in spite of what the man pages say. Thus, we also disallow
* the case of S_IFIFO. */
if (S_ISFIFO(sb.st_mode)) {
/* File descriptors of FIFO, pipe and kqueue share the same type of file,
* therefore there is no way to tell them apart via stat.st_mode&S_IFMT.
* Fortunately, FIFO is the only one that has a persisted file on filesystem,
* from which we're able to make the distinction for it. */
if (!fcntl(fd, F_GETPATH, path))
return UV_EINVAL;
}
#endif

rc = 0;
EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
Expand Down
33 changes: 32 additions & 1 deletion src/unix/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,37 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}


void uv__tty_close(uv_tty_t* handle) {
int expected;
int fd;

fd = handle->io_watcher.fd;
if (fd == -1)
goto done;

/* This is used for uv_tty_reset_mode() */
do
expected = 0;
while (!atomic_compare_exchange_strong(&termios_spinlock, &expected, 1));

if (fd == orig_termios_fd) {
/* XXX(bnoordhuis) the tcsetattr is probably wrong when there are still
* other uv_tty_t handles active that refer to the same tty/pty but it's
* hard to recognize that particular situation without maintaining some
* kind of process-global data structure, and that still won't work in a
* multi-process setup.
*/
uv__tcsetattr(fd, TCSANOW, &orig_termios);
orig_termios_fd = -1;
}

atomic_store(&termios_spinlock, 0);

done:
uv__stream_close((uv_stream_t*) handle);
}


int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
struct winsize ws;
int err;
Expand Down Expand Up @@ -452,7 +483,7 @@ int uv_tty_reset_mode(void) {
saved_errno = errno;

if (atomic_exchange(&termios_spinlock, 1))
return UV_EBUSY; /* In uv_tty_set_mode(). */
return UV_EBUSY; /* In uv_tty_set_mode() or uv__tty_close(). */

err = 0;
if (orig_termios_fd != -1)
Expand Down
57 changes: 45 additions & 12 deletions test/test-poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,26 +626,59 @@ TEST_IMPL(poll_unidirectional) {


/* Windows won't let you open a directory so we open a file instead.
* OS X lets you poll a file so open the $PWD instead. Both fail
* on Linux so it doesn't matter which one we pick. Both succeed
* on FreeBSD, Solaris and AIX so skip the test on those platforms.
* OS X lets you poll a file so open the $PWD instead. Both fail
* on Linux so it doesn't matter which one we pick. Both succeed
* on Solaris and AIX so skip the test on those platforms.
* On *BSD/Darwin, we disallow polling of regular files, directories.
* In addition to regular files, we also disallow FIFOs on Darwin.
*/
#ifdef __APPLE__
#define TEST_POLL_FIFO_PATH "/tmp/uv-test-poll-fifo"
#endif
TEST_IMPL(poll_bad_fdtype) {
#if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \
#if !defined(__sun) && \
!defined(_AIX) && !defined(__MVS__) && \
!defined(__OpenBSD__) && !defined(__CYGWIN__) && !defined(__MSYS__) && \
!defined(__NetBSD__)
!defined(__CYGWIN__) && !defined(__MSYS__)
uv_poll_t poll_handle;
int fd;
int fd[2];

#if defined(_WIN32)
fd = _open("test/fixtures/empty_file", UV_FS_O_RDONLY);
fd[0] = _open("test/fixtures/empty_file", UV_FS_O_RDONLY);
#else
fd = open(".", UV_FS_O_RDONLY);
fd[0] = open(".", UV_FS_O_RDONLY);
#endif
ASSERT_NE(fd[0], -1);
ASSERT_NE(0, uv_poll_init(uv_default_loop(), &poll_handle, fd[0]));
ASSERT_OK(close(fd[0]));
#if defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
fd[0] = open("test/fixtures/empty_file", UV_FS_O_RDONLY);
ASSERT_NE(fd[0], -1);
/* Regular files should be banned from kqueue. */
ASSERT_NE(0, uv_poll_init(uv_default_loop(), &poll_handle, fd[0]));
ASSERT_OK(close(fd[0]));
#ifdef __APPLE__
ASSERT_OK(pipe(fd));
/* Pipes should be permitted in kqueue. */
ASSERT_EQ(0, uv_poll_init(uv_default_loop(), &poll_handle, fd[0]));
ASSERT_OK(close(fd[0]));
ASSERT_OK(close(fd[1]));

ASSERT_OK(mkfifo(TEST_POLL_FIFO_PATH, 0600));
fd[0] = open(TEST_POLL_FIFO_PATH, O_RDONLY | O_NONBLOCK);
ASSERT_NE(fd[0], -1);
fd[1] = open(TEST_POLL_FIFO_PATH, O_WRONLY | O_NONBLOCK);
ASSERT_NE(fd[1], -1);
/* FIFOs should be banned from kqueue. */
ASSERT_NE(0, uv_poll_init(uv_default_loop(), &poll_handle, fd[0]));
ASSERT_OK(close(fd[0]));
ASSERT_OK(close(fd[1]));
unlink(TEST_POLL_FIFO_PATH);
#endif
#endif
ASSERT_NE(fd, -1);
ASSERT_NE(0, uv_poll_init(uv_default_loop(), &poll_handle, fd));
ASSERT_OK(close(fd));
#endif

MAKE_VALGRIND_HAPPY(uv_default_loop());
Expand Down

0 comments on commit 06bab9c

Please sign in to comment.