problem with glibc strerror messages translation (was: Could not open file pg_xlog/000000010....) - Mailing list pgsql-bugs

From Sergey Burladyan
Subject problem with glibc strerror messages translation (was: Could not open file pg_xlog/000000010....)
Date
Msg-id 87pqvezp3w.fsf@home.progtech.ru
Whole thread Raw
In response to Could not open file pg_xlog/000000010....  (Victor <only-victor@mail.ru>)
Responses Re: problem with glibc strerror messages translation (was: Could not open file pg_xlog/000000010....)
List pgsql-bugs
Tom Lane <tgl@sss.pgh.pa.us> writes:

> Victor <only-victor@mail.ru> writes:
> > Oct 12 17:53:25 localhost postgres[26997]: [1753-1] PANIC:  could not
> > open file "pg_xlog/000000010000000000000007" (log file 0, segment
> > 7): ???????????? ????????
>
> Hm, where's the rest of that error message?  You should certainly not
> have gotten just question-marks there.

IMHO you can receive question-marks here if lc_messages in postgresql.conf
do not match with locale from environment at server start, for example:

correctly translated and displayed:
$ LANG=ru_RU.UTF-8 ../bin/postgres -D d -k`pwd`/s
2010-10-13 05:34:39 MSD 14796 4cb50caf.39cc FATAL:  XX000: could not create shared memory segment: Недопустимый
аргумент

incorrect, question-marks only:
$ LANG=C ../bin/postgres -D d -k`pwd`/s
2010-10-13 05:34:54 MSD 14798 4cb50cbd.39ce FATAL:  XX000: could not create shared memory segment: ????????????
????????

error message received from function strerror(). It use gettext (in glibc) for messages translation.
man gettext say this:
 In both cases, the functions also use the LC_CTYPE locale facet in order to
 convert the translated message from the translator's codeset to the current
 locale's codeset, unless overridden by a prior call to the
 bind_textdomain_codeset function.

but when postgres starting, it set LC_CTYPE to current locale (I used gdb for monitoring):

$ LANG=C gdb --args ../bin/postgres -D d -k`pwd`/s
(gdb) break setlocale
Breakpoint 1 at 0x453118
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>p {"LC_CTYPE         ", "LC_NUMERIC       ", "LC_TIME          ", "LC_COLLATE       ", "LC_MONETARY      ",
"LC_MESSAGES     ", "LC_ALL           ", "LC_PAPER         ", "LC_NAME          ", "LC_ADDRESS       ", "LC_TELEPHONE
 ", "LC_MEASUREMENT   ", "LC_IDENTIFICATION"}[category] 
>c
>end
(gdb) set pagination off
(gdb) r
Starting program: /home/seb/inst/pg-dev/bin/postgres -D d -k/home/seb/inst/pg-dev/var/s
Breakpoint 1, *__GI_setlocale (category=3, locale=0x7ff627 "") at setlocale.c:199
199     setlocale.c: No such file or directory.
        in setlocale.c
$1 = "LC_COLLATE       "

Breakpoint 1, *__GI_setlocale (category=0, locale=0x7ff627 "") at setlocale.c:199
199     in setlocale.c
$2 = "LC_CTYPE         "

Breakpoint 1, *__GI_setlocale (category=5, locale=0x7ff627 "") at setlocale.c:199
199     in setlocale.c
$3 = "LC_MESSAGES      "

. . .

Breakpoint 1, *__GI_setlocale (category=5, locale=0xb31e10 "ru_RU.UTF-8") at setlocale.c:199
199     in setlocale.c
$29 = "LC_MESSAGES      "

so, if current environment do not match with lc_messages in postgresql.conf
- glibc cannot translate error message.

simple test program in attachment
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <libintl.h>

/*
 * http://sourceware.org/git/?p=glibc.git;a=blob;f=string/_strerror.c
 * http://sourceware.org/git/?p=glibc.git;a=blob;f=include/libintl.h
 *
 * man gettext
 *
 * In both cases, the functions also use the LC_CTYPE locale facet in order to
 * convert the translated message from the translator's codeset to the current
 * locale's codeset, unless overridden by a prior call to the
 * bind_textdomain_codeset function.
 *
 */

int main()
{
    printf("LC_MESSAGES: %s\n", setlocale(LC_MESSAGES, "ru_RU.UTF-8"));
    /* postgres do this at starting */
    printf("LC_CTYPE: %s\n", setlocale(LC_CTYPE, ""));
    /* can be fixed like this, but _libc_intl_domainname is private :( */
    //printf("bind_textdomain_codeset: %s\n", bind_textdomain_codeset(/*_libc_intl_domainname*/"libc", "UTF-8"));
    printf("msg: %s\n", strerror(22));
    return 0;
}
correct:
$ ./a.out 
LC_MESSAGES: ru_RU.UTF-8
LC_CTYPE: ru_RU.UTF-8
msg: Недопустимый аргумент

incorrect:
$ LANG=C ./a.out 
LC_MESSAGES: ru_RU.UTF-8
LC_CTYPE: C
msg: ???????????? ????????

-- 
Sergey Burladyan

pgsql-bugs by date:

Previous
From: Tom Lane
Date:
Subject: Re: Could not open file pg_xlog/000000010....
Next
From: Robert Haas
Date:
Subject: Re: BUG #5704: not correct restrictions plperlu