Ensure to close pipes when TCPSocket.new finishes processing (#12181)

`TCPSocket.new` with HEv2 uses three threads.
The last of these threads to exit closed pipes.
However, if pipes were open at the end of the main thread, they would leak.
This change avoids this by closing pipes at the end of the main thread.
This commit is contained in:
Misaki Shioi 2024-11-29 18:49:02 +09:00 committed by GitHub
parent 22e1a8c478
commit 49d2e79fb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2024-11-29 09:49:32 +00:00
Merged-By: shioimm <shioi.mm@gmail.com>
3 changed files with 15 additions and 7 deletions

View File

@ -229,6 +229,7 @@ struct fast_fallback_inetsock_arg
rb_nativethread_lock_t *lock;
struct fast_fallback_getaddrinfo_entry *getaddrinfo_entries[2];
struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared;
int wait;
int connection_attempt_fds_size;
int *connection_attempt_fds;
VALUE test_mode_settings;
@ -313,7 +314,7 @@ cancel_fast_fallback(void *ptr)
{
arg->cancelled = true;
char notification = SELECT_CANCELLED;
if ((write(arg->notify, &notification, 1)) < 0) {
if (arg->notify != -1 && (write(arg->notify, &notification, 1)) < 0) {
rb_syserr_fail(errno, "write(2)");
}
}
@ -554,7 +555,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
pthread_t threads[arg->family_size];
char resolved_type[2];
ssize_t resolved_type_size;
int hostname_resolution_waiter = 0, hostname_resolution_notifier = 0;
int hostname_resolution_waiter = -1, hostname_resolution_notifier = -1;
int pipefd[2];
fd_set readfds, writefds;
@ -587,6 +588,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
if ((fcntl(hostname_resolution_waiter, F_SETFL, waiter_flags | O_NONBLOCK)) < 0) {
rb_syserr_fail(errno, "fcntl(2)");
}
arg->wait = hostname_resolution_waiter;
hostname_resolution_notifier = pipefd[1];
wait_arg.readfds = &readfds;
@ -599,7 +601,6 @@ init_fast_fallback_inetsock_internal(VALUE v)
rb_nativethread_lock_initialize(arg->getaddrinfo_shared->lock);
arg->getaddrinfo_shared->notify = hostname_resolution_notifier;
arg->getaddrinfo_shared->wait = hostname_resolution_waiter;
arg->getaddrinfo_shared->connection_attempt_fds = arg->connection_attempt_fds;
arg->getaddrinfo_shared->connection_attempt_fds_size = arg->connection_attempt_fds_size;
arg->getaddrinfo_shared->cancelled = false;
@ -1191,6 +1192,10 @@ fast_fallback_inetsock_cleanup(VALUE v)
arg->local.res = 0;
}
if (arg->wait != -1) close(arg->wait);
if (getaddrinfo_shared->notify != -1) close(getaddrinfo_shared->notify);
getaddrinfo_shared->notify = -1;
if (getaddrinfo_shared) {
if (arg->family_size == 1) {
free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared);

View File

@ -3033,8 +3033,6 @@ free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **
(*shared)->node = NULL;
free((*shared)->service);
(*shared)->service = NULL;
close((*shared)->notify);
close((*shared)->wait);
rb_nativethread_lock_destroy((*shared)->lock);
free(*shared);
*shared = NULL;
@ -3057,6 +3055,11 @@ do_fast_fallback_getaddrinfo(void *ptr)
struct fast_fallback_getaddrinfo_shared *shared = entry->shared;
int err = 0, need_free = 0, shared_need_free = 0;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, NULL);
err = numeric_getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
if (err != 0) {
@ -3101,7 +3104,7 @@ do_fast_fallback_getaddrinfo(void *ptr)
const char notification = entry->family == AF_INET6 ?
IPV6_HOSTNAME_RESOLVED : IPV4_HOSTNAME_RESOLVED;
if ((write(shared->notify, &notification, 1)) < 0) {
if (shared->notify != -1 && (write(shared->notify, &notification, 1)) < 0) {
entry->err = errno;
entry->has_syserr = true;
}

View File

@ -440,7 +440,7 @@ struct fast_fallback_getaddrinfo_entry
struct fast_fallback_getaddrinfo_shared
{
int wait, notify, refcount, connection_attempt_fds_size;
int notify, refcount, connection_attempt_fds_size;
int cancelled;
int *connection_attempt_fds;
char *node, *service;