public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: "Ondřej Bílka" <neleai@seznam.cz>
To: libc-alpha@sourceware.org
Subject: Re: [PATCH 2a][BZ #15607] Make setenv thread safe.
Date: Sat, 09 Nov 2013 09:31:00 -0000	[thread overview]
Message-ID: <20131109093122.GA8314@domone> (raw)
In-Reply-To: <20131015122207.GA2282@domone.podge>

ping
On Tue, Oct 15, 2013 at 02:22:07PM +0200, Ondřej Bílka wrote:
> On Tue, Oct 15, 2013 at 11:34:50AM +0200, Ondřej Bílka wrote:
> > Hi,
> > 
> > In setenv.c file a logic of adding element is needlessly duplicated
> > based on if we extend __environ or not. This can be easily fixed in
> > following way:
> > 
> Previos patch cleared setenv implementation for this patch. 
> A problem in this bug entry is that getenv can segfault when other
> thread calls setenv which reallocates environment. As we need to leak
> getenv entries we can also affort to leak old enviroments.
> 
> We need to double size for each reallocation to ensure that amount of
> space allocated is at most double of space occupied by current environ
> array.
> 
> This does not make getenv completely reentrant, a unsetenv could cause a
> getenv call with unrelated key to fail.
> 
> A doubling of allocations is needed for future speeding lookups by hash
> table, in case that we do not want this patch I will prepare a 2b
> version that deallocates environments.
> 
> This patch causes a intl/mtrace-tst-gettext fail with memory not freed
> message. How to suppress this?
> 
> 
> 	[BZ #15607]
> 	* stdlib/setenv.c: Make getenv thread safe.
> 
> ---
>  stdlib/setenv.c | 35 +++++++++++++++++------------------
>  1 file changed, 17 insertions(+), 18 deletions(-)
> 
> diff --git a/stdlib/setenv.c b/stdlib/setenv.c
> index 5524cc0..29faebf 100644
> --- a/stdlib/setenv.c
> +++ b/stdlib/setenv.c
> @@ -97,7 +97,7 @@ static void *known_values;
>  /* If this variable is not a null pointer we allocated the current
>     environment.  */
>  static char **last_environ;
> -
> +static size_t allocated;
>  
>  /* This function is used by `setenv' and `putenv'.  The difference between
>     the two functions is that for the former must create a new string which
> @@ -133,28 +133,34 @@ __add_to_environ (name, value, combined, replace)
>  	  ++size;
>      }
>  
> -  if (ep == NULL || __builtin_expect (*ep == NULL, 1))
> +  if (ep == NULL || (*ep == NULL && __environ != last_environ) ||
> +      (__environ == last_environ && size == allocated - 1))
>      {
>        char **new_environ;
> +      size_t i;
> +      size_t newsize = 2 * size + 2;
>  
> -      /* We allocated this space; we can extend it.  */
> -      new_environ = (char **) realloc (last_environ,
> -				       (size + 2) * sizeof (char *));
> +      /* We need to keep old environments to make getenv thread safe.  */
> +      new_environ = (char **) malloc ((newsize + 1) * sizeof (char *));
>        if (new_environ == NULL)
>  	{
>  	  UNLOCK;
>  	  return -1;
>  	}
>  
> -      if (__environ != last_environ)
> -	memcpy ((char *) new_environ, (char *) __environ,
> -		size * sizeof (char *));
> +      /* To keep valgrind from reporting leak.  */
> +      new_environ[0] = last_environ;
> +      new_environ++;
>  
> -      new_environ[size] = NULL;
> -      ep = new_environ + size;
> -      new_environ[size + 1] = NULL;
> +      memcpy ((char *) new_environ, (char *) __environ,
> +              size * sizeof (char *));
> +
> +      for (i = size; i < newsize; i++)
> +        new_environ[i] = NULL;
>  
>        last_environ = __environ = new_environ;
> +      allocated = newsize;
> +      ep = new_environ + size;
>      }
>    if (*ep == NULL || replace)
>      {
> @@ -288,13 +294,6 @@ clearenv (void)
>  {
>    LOCK;
>  
> -  if (__environ == last_environ && __environ != NULL)
> -    {
> -      /* We allocated this environment so we can free it.  */
> -      free (__environ);
> -      last_environ = NULL;
> -    }
> -
>    /* Clear the environment pointer removes the whole environment.  */
>    __environ = NULL;
>  
> -- 
> 1.8.4.rc3

  reply	other threads:[~2013-11-09  9:31 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-15  9:34 [PATCH] Deduplicate setenv.c Ondřej Bílka
2013-10-15 12:22 ` [PATCH 2a][BZ #15607] Make setenv thread safe Ondřej Bílka
2013-11-09  9:31   ` Ondřej Bílka [this message]
2015-07-11 21:47     ` [PING][PATCH " Ondřej Bílka
2013-10-18 14:47 ` [PATCH] Deduplicate setenv.c Ondřej Bílka
2013-10-23 13:17 ` [PING][BZ #15894][PATCH] " Ondřej Bílka
2013-10-30 15:33   ` Ondřej Bílka
2013-11-05 14:26     ` [PING^3][BZ " Ondřej Bílka
2013-11-27 13:34       ` [PING^4][BZ " Ondřej Bílka
2013-12-04 11:57         ` [PING^5][BZ " Ondřej Bílka
2014-02-08  0:23           ` [PING^6][BZ " Ondřej Bílka
2014-02-08 14:52             ` Mike Frysinger
2014-02-10 12:59               ` Ondřej Bílka
2014-02-11 10:38                 ` Siddhesh Poyarekar
2014-02-11 11:46                   ` Ondřej Bílka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131109093122.GA8314@domone \
    --to=neleai@seznam.cz \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).