fix: Socket SO_ACCEPTCONN hack for WSL1

As SO_ACCEPTCONN does not work properly on these systems,
we have to rely on Darling to report listening sockets in
libsystem_kernel and keep a registry of listening sockets
in libkqueue.
This commit is contained in:
Trung Nguyen 2022-08-25 09:18:03 +07:00
parent 8572682de1
commit 4e6a9f048b
No known key found for this signature in database
GPG Key ID: 8C6357127C5190F6
5 changed files with 119 additions and 4 deletions

View File

@ -97,6 +97,17 @@ else()
endif()
source_group(src FILES ${SRC})
if (DARLING)
file(GLOB SRC_DARLING
src/darling/*.h
src/darling/*.c
)
list (APPEND SRC ${SRC_DARLING})
add_definitions(
-DDARLING=1
)
endif (DARLING)
#includes
include_directories(
include

View File

@ -24,6 +24,10 @@
#include "private.h"
#ifdef DARLING
#include "../darling/listenregistry.h"
#endif
int DEBUG_KQUEUE = 0;
char *KQUEUE_DEBUG_IDENT = "KQ";
@ -258,6 +262,10 @@ kqueue_closed_fd(int fd)
if (context.dynamic_buffer) {
free(context.kqs_to_check);
}
#ifdef DARLING
__darling_kqueue_unregister_listen(fd);
#endif
}
// FIXME: this can race with someone closing the old FD right after it's dup'ed but before we're informed.
@ -279,6 +287,11 @@ kqueue_dup(int oldfd, int newfd)
}
pthread_mutex_unlock(&kq_mtx);
#ifdef DARLING
if (__darling_kqueue_get_listen_status(oldfd))
__darling_kqueue_register_listen(newfd);
#endif
}
static void _kqueue_close_atfork_cb(int kqfd, void* kqptr, void* private)

View File

@ -0,0 +1,71 @@
#include <pthread.h>
#include <stdlib.h>
#include "listenregistry.h"
static pthread_mutex_t registry_mtx = PTHREAD_MUTEX_INITIALIZER;
static int* registry_vector = NULL;
static size_t registry_vector_capacity = 0;
static size_t registry_vector_size = 0;
#define REGISTRY_VECTOR_INITIAL_CAPACITY (8)
bool __darling_kqueue_get_listen_status(int fd)
{
bool result = false;
pthread_mutex_lock(&registry_mtx);
if (registry_vector != NULL) {
for (size_t i = 0; i < registry_vector_size; ++i) {
if (registry_vector[i] == fd)
result = true;
}
}
pthread_mutex_unlock(&registry_mtx);
return result;
}
void __darling_kqueue_register_listen(int fd)
{
pthread_mutex_lock(&registry_mtx);
if (registry_vector == NULL) {
registry_vector = malloc(REGISTRY_VECTOR_INITIAL_CAPACITY);
if (registry_vector == NULL)
goto quit;
registry_vector_capacity = REGISTRY_VECTOR_INITIAL_CAPACITY;
} else if (registry_vector_size == registry_vector_capacity) {
int* newPtr = realloc(registry_vector, registry_vector_capacity * 2);
if (newPtr == NULL)
goto quit;
registry_vector = newPtr;
registry_vector_capacity *= 2;
}
for (size_t i = 0; i < registry_vector_size; ++i) {
if (registry_vector[i] == fd)
goto quit;
}
registry_vector[registry_vector_size] = fd;
++registry_vector_size;
quit:
pthread_mutex_unlock(&registry_mtx);
}
void __darling_kqueue_unregister_listen(int fd)
{
pthread_mutex_lock(&registry_mtx);
for (size_t i = 0; i < registry_vector_size; ++i) {
while (registry_vector[i] == fd) {
registry_vector[i] = registry_vector[registry_vector_size];
--registry_vector_size;
}
}
pthread_mutex_unlock(&registry_mtx);
}

View File

@ -0,0 +1,10 @@
#ifndef _DARLING_LISTENREGISTRY_H
#define _DARLING_LISTENREGISTRY_H
#include "../common/private.h"
bool VISIBLE __darling_kqueue_get_listen_status(int fd);
void VISIBLE __darling_kqueue_register_listen(int fd);
void VISIBLE __darling_kqueue_unregister_listen(int fd);
#endif

View File

@ -19,6 +19,10 @@
#include <pthread.h>
#include "../common/private.h"
#ifdef DARLING
#include "../darling/listenregistry.h"
#endif
/*
* Per-thread epoll event buffer used to ferry data between
* kevent_wait() and kevent_copyout().
@ -365,15 +369,21 @@ linux_get_descriptor_type(struct knote *kn)
case ENOTSOCK: /* same as lsock = 0 */
return (0);
break;
#ifdef DARLING
/* Hack for WSL1 issue: https://github.com/microsoft/WSL/issues/8757 */
case EINVAL:
lsock = __darling_kqueue_get_listen_status(kn->kev.ident);
break;
#endif
default:
dbg_perror("getsockopt(3)");
return (-1);
}
} else {
if (lsock)
kn->kn_flags |= KNFL_PASSIVE_SOCKET;
return (0);
}
if (lsock)
kn->kn_flags |= KNFL_PASSIVE_SOCKET;
return (0);
}
char *