Skip to content

Commit 49d2e79

Browse files
authored
Ensure to close pipes when TCPSocket.new finishes processing (ruby#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.
1 parent 22e1a8c commit 49d2e79

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

ext/socket/ipsocket.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ struct fast_fallback_inetsock_arg
229229
rb_nativethread_lock_t *lock;
230230
struct fast_fallback_getaddrinfo_entry *getaddrinfo_entries[2];
231231
struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared;
232+
int wait;
232233
int connection_attempt_fds_size;
233234
int *connection_attempt_fds;
234235
VALUE test_mode_settings;
@@ -313,7 +314,7 @@ cancel_fast_fallback(void *ptr)
313314
{
314315
arg->cancelled = true;
315316
char notification = SELECT_CANCELLED;
316-
if ((write(arg->notify, &notification, 1)) < 0) {
317+
if (arg->notify != -1 && (write(arg->notify, &notification, 1)) < 0) {
317318
rb_syserr_fail(errno, "write(2)");
318319
}
319320
}
@@ -554,7 +555,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
554555
pthread_t threads[arg->family_size];
555556
char resolved_type[2];
556557
ssize_t resolved_type_size;
557-
int hostname_resolution_waiter = 0, hostname_resolution_notifier = 0;
558+
int hostname_resolution_waiter = -1, hostname_resolution_notifier = -1;
558559
int pipefd[2];
559560
fd_set readfds, writefds;
560561

@@ -587,6 +588,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
587588
if ((fcntl(hostname_resolution_waiter, F_SETFL, waiter_flags | O_NONBLOCK)) < 0) {
588589
rb_syserr_fail(errno, "fcntl(2)");
589590
}
591+
arg->wait = hostname_resolution_waiter;
590592

591593
hostname_resolution_notifier = pipefd[1];
592594
wait_arg.readfds = &readfds;
@@ -599,7 +601,6 @@ init_fast_fallback_inetsock_internal(VALUE v)
599601
rb_nativethread_lock_initialize(arg->getaddrinfo_shared->lock);
600602

601603
arg->getaddrinfo_shared->notify = hostname_resolution_notifier;
602-
arg->getaddrinfo_shared->wait = hostname_resolution_waiter;
603604
arg->getaddrinfo_shared->connection_attempt_fds = arg->connection_attempt_fds;
604605
arg->getaddrinfo_shared->connection_attempt_fds_size = arg->connection_attempt_fds_size;
605606
arg->getaddrinfo_shared->cancelled = false;
@@ -1191,6 +1192,10 @@ fast_fallback_inetsock_cleanup(VALUE v)
11911192
arg->local.res = 0;
11921193
}
11931194

1195+
if (arg->wait != -1) close(arg->wait);
1196+
if (getaddrinfo_shared->notify != -1) close(getaddrinfo_shared->notify);
1197+
getaddrinfo_shared->notify = -1;
1198+
11941199
if (getaddrinfo_shared) {
11951200
if (arg->family_size == 1) {
11961201
free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared);

ext/socket/raddrinfo.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3033,8 +3033,6 @@ free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **
30333033
(*shared)->node = NULL;
30343034
free((*shared)->service);
30353035
(*shared)->service = NULL;
3036-
close((*shared)->notify);
3037-
close((*shared)->wait);
30383036
rb_nativethread_lock_destroy((*shared)->lock);
30393037
free(*shared);
30403038
*shared = NULL;
@@ -3057,6 +3055,11 @@ do_fast_fallback_getaddrinfo(void *ptr)
30573055
struct fast_fallback_getaddrinfo_shared *shared = entry->shared;
30583056
int err = 0, need_free = 0, shared_need_free = 0;
30593057

3058+
sigset_t set;
3059+
sigemptyset(&set);
3060+
sigaddset(&set, SIGPIPE);
3061+
pthread_sigmask(SIG_BLOCK, &set, NULL);
3062+
30603063
err = numeric_getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
30613064

30623065
if (err != 0) {
@@ -3101,7 +3104,7 @@ do_fast_fallback_getaddrinfo(void *ptr)
31013104
const char notification = entry->family == AF_INET6 ?
31023105
IPV6_HOSTNAME_RESOLVED : IPV4_HOSTNAME_RESOLVED;
31033106

3104-
if ((write(shared->notify, &notification, 1)) < 0) {
3107+
if (shared->notify != -1 && (write(shared->notify, &notification, 1)) < 0) {
31053108
entry->err = errno;
31063109
entry->has_syserr = true;
31073110
}

ext/socket/rubysocket.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ struct fast_fallback_getaddrinfo_entry
440440

441441
struct fast_fallback_getaddrinfo_shared
442442
{
443-
int wait, notify, refcount, connection_attempt_fds_size;
443+
int notify, refcount, connection_attempt_fds_size;
444444
int cancelled;
445445
int *connection_attempt_fds;
446446
char *node, *service;

0 commit comments

Comments
 (0)