From: "Ondřej Bílka" <neleai@seznam.cz>
To: libc-alpha@sourceware.org
Subject: [PATCH 2a][BZ #15607] Make setenv thread safe.
Date: Tue, 15 Oct 2013 12:22:00 -0000 [thread overview]
Message-ID: <20131015122207.GA2282@domone.podge> (raw)
In-Reply-To: <20131015093450.GA1459@domone.podge>
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
next prev parent reply other threads:[~2013-10-15 12:22 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 ` Ondřej Bílka [this message]
2013-11-09 9:31 ` [PATCH 2a][BZ #15607] Make setenv thread safe Ondřej Bílka
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=20131015122207.GA2282@domone.podge \
--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).