Re: initdb failure in CVS - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: initdb failure in CVS
Date
Msg-id 40994A10.7090802@dunslane.net
Whole thread Raw
In response to initdb failure in CVS  (Bruce Momjian <pgman@candle.pha.pa.us>)
Responses Re: initdb failure in CVS  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
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






pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: initdb failure in CVS
Next
From: Steve Atkins
Date:
Subject: Re: PostgreSQL pre-fork speedup