mjit: get rid of memory leak in pause+resume loop
pthread_atfork is not idempotent and repeatedly calling it causes it to register the same hook repeatedly; leading to unbound memory growth. Ruby already has a (confusing-named) internal API for to call in the forked child process: rb_thread_atfork Call the MJIT child_after_fork hook inside that to prevent unbound growth with the following loop: loop do RubyVM::MJIT.pause RubyVM::MJIT.resume end git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63884 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a1e589498d
commit
c93adfc170
14
mjit.c
14
mjit.c
@ -117,7 +117,7 @@ extern void rb_native_cond_signal(rb_nativethread_cond_t *cond);
|
|||||||
extern void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
|
extern void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
|
||||||
extern void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
|
extern void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
|
||||||
|
|
||||||
extern int rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void));
|
extern int rb_thread_create_mjit_thread(void (*worker_func)(void));
|
||||||
|
|
||||||
/* process.c */
|
/* process.c */
|
||||||
rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options,
|
rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options,
|
||||||
@ -1319,11 +1319,13 @@ init_header_filename(void)
|
|||||||
|
|
||||||
/* This is called after each fork in the child in to switch off MJIT
|
/* This is called after each fork in the child in to switch off MJIT
|
||||||
engine in the child as it does not inherit MJIT threads. */
|
engine in the child as it does not inherit MJIT threads. */
|
||||||
static void
|
void
|
||||||
child_after_fork(void)
|
mjit_child_after_fork(void)
|
||||||
{
|
{
|
||||||
verbose(3, "Switching off MJIT in a forked child");
|
if (mjit_enabled) {
|
||||||
mjit_enabled = FALSE;
|
verbose(3, "Switching off MJIT in a forked child");
|
||||||
|
mjit_enabled = FALSE;
|
||||||
|
}
|
||||||
/* TODO: Should we initiate MJIT in the forked Ruby. */
|
/* TODO: Should we initiate MJIT in the forked Ruby. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1433,7 +1435,7 @@ start_worker(void)
|
|||||||
stop_worker_p = FALSE;
|
stop_worker_p = FALSE;
|
||||||
worker_stopped = FALSE;
|
worker_stopped = FALSE;
|
||||||
|
|
||||||
if (!rb_thread_create_mjit_thread(child_after_fork, worker)) {
|
if (!rb_thread_create_mjit_thread(worker)) {
|
||||||
mjit_enabled = FALSE;
|
mjit_enabled = FALSE;
|
||||||
rb_native_mutex_destroy(&mjit_engine_mutex);
|
rb_native_mutex_destroy(&mjit_engine_mutex);
|
||||||
rb_native_cond_destroy(&mjit_pch_wakeup);
|
rb_native_cond_destroy(&mjit_pch_wakeup);
|
||||||
|
3
thread.c
3
thread.c
@ -4276,6 +4276,8 @@ terminate_atfork_i(rb_thread_t *th, const rb_thread_t *current_th)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* mjit.c */
|
||||||
|
void mjit_child_after_fork(void);
|
||||||
void
|
void
|
||||||
rb_thread_atfork(void)
|
rb_thread_atfork(void)
|
||||||
{
|
{
|
||||||
@ -4286,6 +4288,7 @@ rb_thread_atfork(void)
|
|||||||
|
|
||||||
/* We don't want reproduce CVE-2003-0900. */
|
/* We don't want reproduce CVE-2003-0900. */
|
||||||
rb_reset_random_seed();
|
rb_reset_random_seed();
|
||||||
|
mjit_child_after_fork();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1767,14 +1767,12 @@ mjit_worker(void *arg)
|
|||||||
|
|
||||||
/* Launch MJIT thread. Returns FALSE if it fails to create thread. */
|
/* Launch MJIT thread. Returns FALSE if it fails to create thread. */
|
||||||
int
|
int
|
||||||
rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void))
|
rb_thread_create_mjit_thread(void (*worker_func)(void))
|
||||||
{
|
{
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
pthread_t worker_pid;
|
pthread_t worker_pid;
|
||||||
int ret = FALSE;
|
int ret = FALSE;
|
||||||
|
|
||||||
pthread_atfork(NULL, NULL, child_hook);
|
|
||||||
|
|
||||||
if (pthread_attr_init(&attr) != 0) return ret;
|
if (pthread_attr_init(&attr) != 0) return ret;
|
||||||
|
|
||||||
/* jit_worker thread is not to be joined */
|
/* jit_worker thread is not to be joined */
|
||||||
|
@ -790,7 +790,7 @@ mjit_worker(void *arg)
|
|||||||
|
|
||||||
/* Launch MJIT thread. Returns FALSE if it fails to create thread. */
|
/* Launch MJIT thread. Returns FALSE if it fails to create thread. */
|
||||||
int
|
int
|
||||||
rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void))
|
rb_thread_create_mjit_thread(void (*worker_func)(void))
|
||||||
{
|
{
|
||||||
size_t stack_size = 4 * 1024; /* 4KB is the minimum commit size */
|
size_t stack_size = 4 * 1024; /* 4KB is the minimum commit size */
|
||||||
HANDLE thread_id = w32_create_thread(stack_size, mjit_worker, worker_func);
|
HANDLE thread_id = w32_create_thread(stack_size, mjit_worker, worker_func);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user