Re: initdb failure in CVS

From: Andrew Dunstan <andrew(at)dunslane(dot)net>
To: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: initdb failure in CVS
Date: 2004-05-05 20:09:52
Message-ID: 40994A10.7090802@dunslane.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message scott.marlowe 2004-05-05 20:14:39 Re: PostgreSQL pre-fork speedup
Previous Message Shachar Shemesh 2004-05-05 19:59:44 Multiple "selects" returned from a single stored procedure