Bruce Momjian wrote:

I am seeing the following failure of initdb in CVS:
        
        The files belonging to this database system will be owned by user "postgres".
        This user must also own the server process.
        
        The database cluster will be initialized with locale C.
        
        creating directory /u/pg/data ... ok
        creating directory /u/pg/data/global ... ok
        creating directory /u/pg/data/pg_xlog ... ok
        creating directory /u/pg/data/pg_clog ... ok
        creating directory /u/pg/data/base ... ok
        creating directory /u/pg/data/base/1 ... ok
        selecting default max_connections ... 100
        selecting default shared_buffers ... 1000
        creating configuration files ... ok

creating template1 database in /u/pg/data/base/1 ...

           FATAL:  invalid value for parameter "client_encoding": ""

        initdb: child process exited with exit code 1
        initdb: failed
        initdb: removing data directory "/u/pg/data"

The problem seems to be related to a commit made to initdb a few days
ago.

        revision 1.24
        date: 2004/05/05 16:09:31;  author: tgl;  state: Exp;  lines: +23 -2
        Use a more portable technique for unsetting environment variables,
        and unset PGCLIENTENCODING to prevent backend from dying if it's set
        to something incompatible with the -E option.

I don't have any encoding set in my system.




The change is based on this code from here (backend/commands/variable.c):

/*
* unsetenv() works fine, but is BSD, not POSIX, and is not available
* under Solaris, among others. Apparently putenv() called as below
* clears the process-specific environment variables. Other
* reasonable arguments to putenv() (e.g. "TZ=", "TZ", "") result in a
* core dump (under Linux anyway). - thomas 1998-01-26
*/
if (tzbuf[0] == 'T')
{
strcpy(tzbuf, "=");
if (putenv(tzbuf) != 0)
elog(LOG, "could not clear TZ environment variable");
tzset();
}


The Linux man page for putenv says this:

Description for libc4, libc5, glibc: If the argument string is of the
form name, and does not contain an ‘=’ character, then the variable
name is removed from the environment. If putenv() has to allocate a
new array environ, and the previous array was also allocated by
putenv(), then it will be freed. In no case will the old storage asso-
ciated to the environment variable itself be freed.

The libc4 and libc5 and glibc 2.1.2 versions conform to SUSv2: the
pointer string given to putenv() is used. In particular, this string
becomes part of the environment; changing it later will change the
environment. (Thus, it is an error is to call putenv() with an auto-
matic variable as the argument, then return from the calling function
while string is still part of the environment.) However, glibc
2.0-2.1.1 differs: a copy of the string is used. On the one hand this
causes a memory leak, and on the other hand it violates SUSv2. This has
been fixed in glibc2.1.2.

The BSD4.4 version, like glibc 2.0, uses a copy.

I suspect you have seen this latter effect, i.e. it in effect did

putenv("PGCLIENTENCODING=");
putenv("=");

leaving you with an empty string as the env value rather than unsetting it.

Did we actually find a current system where it broke with a straight putenv("LC_ALL")?

cheers

andrew





---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faqs/FAQ.html

Reply via email to