This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/5069] New: env thread safety problem
- From: "zhangxiliang at cn dot fujitsu dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 25 Sep 2007 03:06:53 -0000
- Subject: [Bug libc/5069] New: env thread safety problem
- Reply-to: sourceware-bugzilla at sourceware dot org
Hi everyone,
In the glibc-2.6.1/manual/startup.texi, it says "The value of an environment
variable can be accessed with the @code{getenv} function. This is declared in
the header file @file{stdlib.h}. All of the following functions can be safely
used in multi-threaded programs. It is made sure that concurrent modifications
to the environment do not lead to errors."
But getenv() can't be used safely with setenv(), unsetenv(), clearenv() in
multi-threaded programs on multi-cpu.
When getenv() is being called, if "setenv(), unsetenv(), clearenv()" set
"__environ" to NULL on another cpu, the program will result in segmentation fault.
In glibc, getenv() is called by many functions which are thread safety in
POSIX. So when we use the setenv(),unsetenv(), clearenv(), we can't use those
functions by multi-thread method. I think it should be modified.
I've made a patch to fix it. It applied a read lock in getenv() and write
locks in setenv(), unsetenv(), clearenv().
Because the read lock can't block getenv(), only to block setenv(),
unsetenv(), clearenv().
getenv() itself can achieve full concurrency.
The attachment is the patch.
diff -Nurp glibc-2.6.1.org/stdlib/getenv.c glibc-2.6.1/stdlib/getenv.c
--- glibc-2.6.1.org/stdlib/getenv.c 2005-12-14 17:08:04.000000000 +0800
+++ glibc-2.6.1/stdlib/getenv.c 2007-08-30 16:44:50.000000000 +0800
@@ -23,6 +23,16 @@
#include <string.h>
#include <unistd.h>
+#if _LIBC
+/* This lock protects against simultaneous modifications of `environ'. */
+# include <bits/libc-lock.h>
+__libc_rwlock_define (extern, envlock attribute_hidden)
+# define LOCK __libc_rwlock_rdlock (envlock)
+# define UNLOCK __libc_rwlock_unlock (envlock)
+#else
+# define LOCK
+# define UNLOCK
+#endif
/* Return the value of the environment variable NAME. This implementation
is tuned a bit in that it assumes no environment variable has an empty
@@ -37,9 +47,15 @@ getenv (name)
size_t len = strlen (name);
char **ep;
uint16_t name_start;
+ char *env_value;
+
+ LOCK;
if (__environ == NULL || name[0] == '\0')
- return NULL;
+ {
+ UNLOCK;
+ return NULL;
+ }
if (name[1] == '\0')
{
@@ -64,7 +80,11 @@ getenv (name)
| (((unsigned char *) *ep)[1] << 8));
#endif
if (name_start == ep_start)
- return &(*ep)[2];
+ {
+ env_value = &(*ep)[2];
+ UNLOCK;
+ return env_value;
+ }
}
}
else
@@ -89,10 +109,15 @@ getenv (name)
if (name_start == ep_start && !strncmp (*ep + 2, name, len)
&& (*ep)[len + 2] == '=')
- return &(*ep)[len + 3];
+ {
+ env_value = &(*ep)[len + 3];
+ UNLOCK;
+ return env_value;
+ }
}
}
+ UNLOCK;
return NULL;
}
libc_hidden_def (getenv)
diff -Nurp glibc-2.6.1.org/stdlib/setenv.c glibc-2.6.1/stdlib/setenv.c
--- glibc-2.6.1.org/stdlib/setenv.c 2005-12-14 18:44:05.000000000 +0800
+++ glibc-2.6.1/stdlib/setenv.c 2007-08-29 17:21:50.000000000 +0800
@@ -48,9 +48,9 @@ extern char **environ;
#if _LIBC
/* This lock protects against simultaneous modifications of `environ'. */
# include <bits/libc-lock.h>
-__libc_lock_define_initialized (static, envlock)
-# define LOCK __libc_lock_lock (envlock)
-# define UNLOCK __libc_lock_unlock (envlock)
+__libc_rwlock_define_initialized (, envlock attribute_hidden)
+# define LOCK __libc_rwlock_wrlock (envlock)
+# define UNLOCK __libc_rwlock_unlock (envlock)
#else
# define LOCK
# define UNLOCK
--
Summary: env thread safety problem
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: libc
AssignedTo: drepper at redhat dot com
ReportedBy: zhangxiliang at cn dot fujitsu dot com
CC: glibc-bugs at sources dot redhat dot com,zhangxiliang at
cn dot fujitsu dot com
http://sourceware.org/bugzilla/show_bug.cgi?id=5069
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.