From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24570 invoked by alias); 10 Aug 2011 08:40:24 -0000 Received: (qmail 24137 invoked by uid 22791); 10 Aug 2011 08:40:19 -0000 X-SWARE-Spam-Status: No, hits=-2.8 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00,TW_VS X-Spam-Check-By: sourceware.org Received: from localhost (HELO sourceware.org) (127.0.0.1) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 10 Aug 2011 08:39:57 +0000 From: "yanagimoto at np dot css.fujitsu.com" To: glibc-bugs@sources.redhat.com Subject: [Bug libc/13071] New: MALLOC_ARENA_MAX environment does not work properly on some race conditions in malloc(). X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: glibc X-Bugzilla-Component: libc X-Bugzilla-Keywords: X-Bugzilla-Severity: minor X-Bugzilla-Who: yanagimoto at np dot css.fujitsu.com X-Bugzilla-Status: NEW X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: drepper.fsp at gmail dot com X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Date: Wed, 10 Aug 2011 08:40:00 -0000 Mailing-List: contact glibc-bugs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: glibc-bugs-owner@sourceware.org X-SW-Source: 2011-08/txt/msg00035.txt.bz2 http://sourceware.org/bugzilla/show_bug.cgi?id=3D13071 Summary: MALLOC_ARENA_MAX environment does not work properly on some race conditions in malloc(). Product: glibc Version: unspecified Status: NEW Severity: minor Priority: P2 Component: libc AssignedTo: drepper.fsp@gmail.com ReportedBy: yanagimoto@np.css.fujitsu.com Created attachment 5889 --> http://sourceware.org/bugzilla/attachment.cgi?id=3D5889 malloc_strictly_observed_arena_max.patch MALLOC_ARENA_MAX environment does not work properly on some race conditions in malloc(). In this case, the number of heaps exceeds=20 the maximum limit, then too much virtual memory is consumed inappropriately. This is a bug, I suppose. malloc() checks whether narenas variable (the number of arena) exceeds narenas_limit (MALLOC_ARENA_MAX) or not in the first part of reused_arena(). However, narenas is incremented _after_ a new arena is created in _int_new_arena(). So if a number of threads in a multi- threaded process rush into malloc() simultaneously, a lot of them can pass the narenas vs. narenas_limit check exceeding the limit, and can call _int_new_arena(). I made a test program, arena_max_test.c, which hits this problem actually. The number of arenas greatly exceeds MALLOC_ARENA_MAX. $ MALLOC_ARENA_MAX=3D10 ./arena_max_test PID =3D 28733 =E3=80=80Arena 0: system bytes =3D 135168 in use bytes =3D 37008 Arena 1: system bytes =3D 135168 in use bytes =3D 2512 ...(snip)... Arena 80: system bytes =3D 135168 in use bytes =3D 2368 Arena 81: system bytes =3D 135168 in use bytes =3D 2368 Total (incl. mmap): system bytes =3D 11083776 in use bytes =3D 235440 max mmap regions =3D 0 max mmap bytes =3D 0 Eighty-two arenas were created even though MALLOC_ARENA_MAX was ten. The process consumed too much virtual memory in this case. $ ps -eo "comm pid vsz rss" | grep "arena_max_test" arena_max_test 28733 6625776 20324 ~~~~~~~(6.3GB) This problem can provoke following situations: - If memory over commit is disabled (vm.overcommit_memory=3D2), the use of the virtual memory too much exerts a baleful influence on the entire system. - Virtual memory space shortage on 32-bit archs, and so on. So I made a solution, introducing a separate counter, new_arena_worker, from narenas to determine whether to call _int_new_arena() or not. Also introducing a new lock, worker_lock, for protecting the counter, but it never make any negative effect if MALLOC_ARENA_MAX environment is not se= t. Even if MALLOC_ARENA_MAX is set, I'd like to hear your opinion about this problem and this patch. diff -Nur a/malloc/arena.c b/malloc/arena.c --- a/malloc/arena.c 2011-06-30 18:22:36.000000000 +0900 +++ b/malloc/arena.c 2011-08-10 17:53:13.000000000 +0900 @@ -79,6 +79,7 @@ static tsd_key_t arena_key; static mutex_t list_lock; #ifdef PER_THREAD +static mutex_t worker_lock; static size_t narenas; static mstate free_list; #endif @@ -354,6 +355,9 @@ if(ar_ptr =3D=3D &main_arena) break; } mutex_init(&list_lock); +#ifdef PER_THREAD + mutex_init(&worker_lock); +#endif atfork_recursive_cntr =3D 0; } @@ -523,6 +527,9 @@ #endif mutex_init(&list_lock); +#ifdef PER_THREAD + mutex_init(&worker_lock); +#endif=20 tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (Void_t *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_al= l2); @@ -982,13 +989,9 @@ return result; } - -static mstate -reused_arena (void) +static int +get_narenas_limit (void) { - if (narenas <=3D mp_.arena_test) - return NULL; - static int narenas_limit; if (narenas_limit =3D=3D 0) { @@ -1006,10 +1009,15 @@ narenas_limit =3D NARENAS_FROM_NCORES (2); } } + return narenas_limit; +} - if (narenas < narenas_limit) - return NULL; +#define is_arena_max(x) \ + ((x) > mp_.arena_test && (x) >=3D get_narenas_limit()) +static mstate +reused_arena (void) +{ mstate result; static mstate next_to_use; if (next_to_use =3D=3D NULL) @@ -1048,10 +1056,37 @@ mstate a; #ifdef PER_THREAD - if ((a =3D get_free_list ()) =3D=3D NULL - && (a =3D reused_arena ()) =3D=3D NULL) - /* Nothing immediately available, so generate a new arena. */ - a =3D _int_new_arena(size); +repeat: + if ((a =3D get_free_list()) =3D=3D NULL) { + if (is_arena_max(narenas)) + a =3D reused_arena(); + else { + /* Nothing immediately available, so try to generate a new arena. */ + + if (mp_.arena_max =3D=3D 0) + a =3D _int_new_arena(size); + else { + /* If MALLOC_ARENA_MAX is set, the arena_max limitation is=20 + observed strictly by using the lock. */ + static int new_arena_worker =3D 1; + + (void)mutex_lock(&worker_lock); + if (is_arena_max(new_arena_worker)) { + (void)mutex_unlock(&worker_lock); + goto repeat; + } + new_arena_worker++; + (void)mutex_unlock(&worker_lock); + + /* Generate a new arena. */ + if ((a =3D _int_new_arena(size)) =3D=3D NULL ) { + (void)mutex_lock(&worker_lock); + new_arena_worker--; + (void)mutex_unlock(&worker_lock); + } + } + } + } #else if(!a_tsd) a =3D a_tsd =3D &main_arena; Regards, Naoki Yanagimoto --=20 Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=3Demail ------- You are receiving this mail because: ------- You are on the CC list for the bug.