The setenv fiasco

Most UNIX developers are familiar with the concept of. Basically, environment variables are a way of passing configuration information to a process. Unlike command-line arguments, which usually need to be specified explicitly, child processes inherit the environment variables that their parents had.

env

The "environment" is an unordered set of key-value pairs. The keys are strings and so are the values. If you have a terminal open, you can see what your current environment looks like by typing. It might look a little bit like this:

ORBIT_SOCKETDIR=/tmp/orbit-cmccabe HOSTNAME=highcastle IMSETTINGS_INTEGRATE_DESKTOP=yes TERM=xterm SHELL=/bin/bash HISTSIZE=1000 GTK_RC_FILES=/etc/gtk/gtkrc:/home/cmccabe/.gtkrc-1.2-gnome2 WINDOWID=44042990 QTDIR=/usr/lib64/qt-3.3 QTINC=/usr/lib64/qt-3.3/include IMSETTINGS_MODULE=none JAVA_OPTS=-Xcheck:jni:nonfatal USER=cmccabe CSCOPE_EDITOR=/usr/bin/vim ...

Environment varibles are a simple and elegant way of passing around configuration information. It's easy to put a bunch of configuration variables into a script, and simply run that script before your application runs. You don't need to write a parser or ask your users to define a new configuration file syntax. Environment variables are accessible from any programming language, and available on any of the major platforms (Linux, Windows, MacOS.)

You can read an environment variable with. You can remove environment variables withor. You can set an environment variable withor

A Day at the Races

None of the POSIX environment functions are thread-safe. Even the humble, which you would expect to be re-entrant, is actually not required to be so. If you create a program that callsfrom multiple threads without using a mutex to serialize access, you are relying on implementation-specific behavior, and POSIX makes no guarantees. I'm not aware of any implementation that will actually have problems with this kind of code, but it's still worth noting. However, if you are modifying the environment in one thread while other threads are reading it, youhave problems on Linux.

The solution is simple: just hold a mutex while accessing or modifying the environment. However, this makes using environment variables a lot more cumbersome. It also makes it difficult to use environment variables in a shared library, or in a scripting language embedded in a larger application.

Modifying the Environment

POSIX doesn't tell you how to allocate space for new environment variables. The original set of environment variables that are passed to the process when it starts areallocated using. So if you add a new environment variable, should the string be allocated usingor not? Nobody knows. Similarly, if you clear an environment variable using, should you callon it? Good question-- but nobody knows the answer.

If you callon a variable that was not originally allocated with, heap corruption will result. On the other hand, if you don't free a variable that wased earlier, that is a memory leak. It's quite a dilemma, and POSIX is no help at all here.

There are actually three ways to set environment variables on Linux. You could use, or modify the global variableis the simplest way. You give it a pointer to a string of the form KEY=VALUE, and it adds that pointer to the global environment.tries to be more clever. It will useto create a new KEY=VALUE string based on the KEY and VALUE that you pass to it.

Personally, I prefer to usewhen adding environment variables. With, you can avoid memory leaks by using statically allocated strings. The other method does not give you this choice.does not exist on HPUX, Solaris, and some other UNIX platforms. However,is mis-implemented ason Mac OS X, FreeBSD, and some ancient Linux platforms.

Conclusion

So there you have it. The situation is a mess. You can't access environment variables safely from multiple threads and can't portably callorwithout introducing memory leaks.

Your best bet is probably to avoid modifying the environment at all, if possible. If that is not possible, try wrapping all accesses to the environment with a mutex , and modifyingyourself, to make sure nobody ising behind your back.

Stepping back a little bit, are these memory leaks and race conditions really such a big deal? Well, even small memory leaks can be annoying if they clutter up the output of tools like, a memory leak diagnosis tool. Also, once you allow incorrect code in your program, it tends to propagate itself, as new programmers look to the old code for examples of how to do things. Do yourself a favor and get it right the first time. As Captain Planet would no doubt say, cleaning up the environment is everyone's responsibility.