summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2024-05-29 16:46:04 +0200
committerJean Boussier <[email protected]>2024-09-05 11:43:46 +0200
commit63cbe3f6ac9feb44a2e43b1f853e2ca7e049316c ()
treedddbbbc8678332d16f9cf5e9630645e233656797 /ext/socket
parent2e5680d304a9cf9a6a2ba582091af6719e839351 (diff)
Proof of Concept: Allow to prevent fork from happening in known fork unsafe API
[Feature #20590] For better of for worse, fork(2) remain the primary provider of parallelism in Ruby programs. Even though it's frowned uppon in many circles, and a lot of literature will simply state that only async-signal safe APIs are safe to use after `fork()`, in practice most APIs work well as long as you are careful about not forking while another thread is holding a pthread mutex. One of the APIs that is known cause fork safety issues is `getaddrinfo`. If you fork while another thread is inside `getaddrinfo`, a mutex may be left locked in the child, with no way to unlock it. I think we could reduce the impact of these problem by preventing in for the most notorious and common cases, by locking around `fork(2)` and known unsafe APIs with a read-write lock.
Notes: Merged: https://.com/ruby/ruby/pull/10864
-rw-r--r--ext/socket/raddrinfo.c16
1 files changed, 14 insertions, 2 deletions
@@ -327,6 +327,12 @@ nogvl_getaddrinfo(void *arg)
return (void *)(VALUE)ret;
}
static int
rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
{
@@ -336,7 +342,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint
arg.service = portp;
arg.hints = hints;
arg.res = ai;
- return (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
}
#elif GETADDRINFO_IMPL == 2
@@ -477,6 +483,12 @@ do_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg)
return ret;
}
static int
rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
{
@@ -493,7 +505,7 @@ start:
}
pthread_t th;
- if (do_pthread_create(&th, do_getaddrinfo, arg) != 0) {
int err = errno;
free_getaddrinfo_arg(arg);
errno = err;