From: | Peter Eisentraut <peter(at)eisentraut(dot)org> |
---|---|
To: | pgsql-committers(at)lists(dot)postgresql(dot)org |
Subject: | pgsql: Tidy up locale thread safety in ECPG library. |
Date: | 2025-03-28 15:28:35 |
Message-ID: | E1tyBdL-001Ra6-2h@gemulon.postgresql.org |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-committers |
Tidy up locale thread safety in ECPG library.
Remove setlocale() and _configthreadlocal() as fallback strategy on
systems that don't have uselocale(), where ECPG tries to control
LC_NUMERIC formatting on input and output of floating point numbers. It
was probably broken on some systems (NetBSD), and the code was also
quite messy and complicated, with obsolete configure tests (Windows).
It was also arguably broken, or at least had unstated environmental
requirements, if pgtypeslib code was called directly.
Instead, introduce PG_C_LOCALE to refer to the "C" locale as a locale_t
value. It maps to the special constant LC_C_LOCALE when defined by libc
(macOS, NetBSD), or otherwise uses a process-lifetime locale_t that is
allocated on first use, just as ECPG previously did itself. The new
replacement might be more widely useful. Then change the float parsing
and printing code to pass that to _l() functions where appropriate.
Unfortunately the portability of those functions is a bit complicated.
First, many obvious and useful _l() functions are missing from POSIX,
though most standard libraries define some of them anyway. Second,
although the thread-safe save/restore technique can be used to replace
the missing ones, Windows and NetBSD refused to implement standard
uselocale(). They might have a point: "wide scope" uselocale() is hard
to combine with other code and error-prone, especially in library code.
Luckily they have the _l() functions we want so far anyway. So we have
to be prepared for both ways of doing things:
1. In ECPG, use strtod_l() for parsing, and supply a port.h replacement
using uselocale() over a limited scope if missing.
2. Inside our own snprintf.c, use three different approaches to format
floats. For frontend code, call libc's snprintf_l(), or wrap libc's
snprintf() in uselocale() if it's missing. For backend code, snprintf.c
can keep assuming that the global locale's LC_NUMERIC is "C" and call
libc's snprintf() without change, for now.
(It might eventually be possible to call our in-tree Ryū routines to
display floats in snprintf.c, given the C-locale-always remit of our
in-tree snprintf(), but this patch doesn't risk changing anything that
complicated.)
Author: Thomas Munro <thomas(dot)munro(at)gmail(dot)com>
Reviewed-by: Peter Eisentraut <peter(at)eisentraut(dot)org>
Reviewed-by: Tristan Partin <tristan(at)partin(dot)io>
Reviewed-by: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Discussion: https://postgr.es/m/CWZBBRR6YA8D.8EHMDRGLCKCD%40neon.tech
Branch
------
master
Details
-------
https://git.postgresql.org/pg/commitdiff/8e993bff5326b00ced137c837fce7cd1e0ecae14
Modified Files
--------------
configure | 2 +-
configure.ac | 2 +
meson.build | 2 +
src/include/pg_config.h.in | 6 ++
src/include/port.h | 31 ++++++++++
src/include/port/win32_port.h | 1 +
src/interfaces/ecpg/ecpglib/connect.c | 39 +------------
src/interfaces/ecpg/ecpglib/data.c | 2 +-
src/interfaces/ecpg/ecpglib/descriptor.c | 37 ------------
src/interfaces/ecpg/ecpglib/ecpglib_extern.h | 12 ----
src/interfaces/ecpg/ecpglib/execute.c | 53 ------------------
src/interfaces/ecpg/pgtypeslib/dt_common.c | 6 +-
src/interfaces/ecpg/pgtypeslib/interval.c | 4 +-
src/interfaces/ecpg/pgtypeslib/numeric.c | 2 +-
src/port/Makefile | 1 +
src/port/locale.c | 84 ++++++++++++++++++++++++++++
src/port/meson.build | 1 +
src/port/snprintf.c | 55 ++++++++++++++++++
18 files changed, 192 insertions(+), 148 deletions(-)
From | Date | Subject | |
---|---|---|---|
Next Message | Masahiko Sawada | 2025-03-28 16:39:34 | pgsql: Fix timestamp overflow in UUIDv7 implementation. |
Previous Message | Peter Eisentraut | 2025-03-28 13:44:08 | pgsql: Cast result of i64abs() back to int64 |