mirror of
https://github.com/darlinghq/darling-libkqueue.git
synced 2024-11-23 03:39:51 +00:00
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:
parent
8572682de1
commit
4e6a9f048b
@ -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
|
||||
|
@ -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)
|
||||
|
71
src/darling/listenregistry.c
Normal file
71
src/darling/listenregistry.c
Normal 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(®istry_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(®istry_mtx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void __darling_kqueue_register_listen(int fd)
|
||||
{
|
||||
pthread_mutex_lock(®istry_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(®istry_mtx);
|
||||
}
|
||||
|
||||
void __darling_kqueue_unregister_listen(int fd)
|
||||
{
|
||||
pthread_mutex_lock(®istry_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(®istry_mtx);
|
||||
}
|
10
src/darling/listenregistry.h
Normal file
10
src/darling/listenregistry.h
Normal 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
|
@ -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 *
|
||||
|
Loading…
Reference in New Issue
Block a user