ruby-changes:54069
From: normal <ko1@a...>
Date: Sun, 9 Dec 2018 04:25:43 +0900 (JST)
Subject: [ruby-changes:54069] normal:r66288 (trunk): thread_pthread.c: fix memory leak from fork loop leapfrog
normal 2018-12-09 04:25:37 +0900 (Sun, 09 Dec 2018) New Revision: 66288 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66288 Log: thread_pthread.c: fix memory leak from fork loop leapfrog Constantly forking a single-threaded process in a loop leads to a memory leak when using POSIX timers. ==> fork_leapfrog.rb <== require 'io/wait' Dir.chdir '/proc' prev = 0 loop do pid = fork exit!(0) if pid # show the number of 4K pages used (Linux-only) n = File.read("#$$/statm").split(-' ')[1].to_i if n > prev puts "#{prev} => #{n}" prev = n end # since Ctrl-C from a terminal can't stop this loop, # allow the user to just hit any key to stop break if STDIN.wait(0) end Modified files: trunk/thread_pthread.c Index: thread_pthread.c =================================================================== --- thread_pthread.c (revision 66287) +++ thread_pthread.c (revision 66288) @@ -1726,16 +1726,12 @@ rb_thread_create_timer_thread(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1726 if (setup_communication_pipe_internal(signal_self_pipe.normal) < 0) return; if (setup_communication_pipe_internal(signal_self_pipe.ub_main) < 0) return; + ubf_timer_create(current); if (owner != current) { /* validate pipe on this process */ - ubf_timer_create(current); sigwait_th = THREAD_INVALID; signal_self_pipe.owner_process = current; } - else if (UBF_TIMER == UBF_TIMER_PTHREAD) { - /* UBF_TIMER_PTHREAD needs to recreate after fork */ - ubf_timer_pthread_create(current); - } } static void @@ -1763,7 +1759,13 @@ ubf_timer_disarm(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1759 static void ubf_timer_destroy(void) { -#if UBF_TIMER == UBF_TIMER_PTHREAD +#if UBF_TIMER == UBF_TIMER_POSIX + if (timer_posix.owner == getpid()) { + if (timer_delete(timer_posix.timerid) < 0) + rb_sys_fail("timer_delete"); + memset(&timer_posix, 0, sizeof(timer_posix)); + } +#elif UBF_TIMER == UBF_TIMER_PTHREAD int err; timer_pthread.owner = 0; @@ -1774,7 +1776,6 @@ ubf_timer_destroy(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1776 rb_raise(rb_eThreadError, "native_thread_join() failed (%d)", err); } #endif -/* no need to destroy real POSIX timers */ } static int -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/