Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf305e84

Browse files
committed
Avoid thread-safety problem in ecpglib.
ecpglib attempts to force the LC_NUMERIC locale to "C" while readingserver output, to avoid problems with strtod() and related functions.Historically it's just issued setlocale() calls to do that, but thathas major problems if we're in a threaded application. setlocale()itself is not required by POSIX to be thread-safe (and indeed is not,on recent OpenBSD). Moreover, its effects are process-wide, so thatwe could cause unexpected results in other threads, or another threadcould change our setting.On platforms having uselocale(), which is required by POSIX:2008,we can avoid these problems by using uselocale() instead. Windowsgoes its own way as usual, but we can make it safe by using_configthreadlocale(). Platforms having neither continue to use theold code, but that should be pretty much nobody among current systems.(Subsequent buildfarm results show that recent NetBSD versions stilllack uselocale(), but it's not a big problem because they also do notsupport non-"C" settings for LC_NUMERIC.)Back-patch of commits8eb4a93 andee27584.Michael Meskes and Tom Lane; thanks also to Takayuki Tsunakawa.Discussion:https://postgr.es/m/31420.1547783697@sss.pgh.pa.us
1 parent7fbdefd commitf305e84

File tree

7 files changed

+132
-10
lines changed

7 files changed

+132
-10
lines changed

‎configure

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14870,7 +14870,7 @@ fi
1487014870
LIBS_including_readline="$LIBS"
1487114871
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
1487214872

14873-
for ac_func in cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range utime utimes wcstombs_l
14873+
for ac_func in cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_rangeuselocaleutime utimes wcstombs_l
1487414874
do :
1487514875
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1487614876
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -15647,6 +15647,17 @@ fi
1564715647

1564815648
# Win32 (really MinGW) support
1564915649
if test "$PORTNAME" = "win32"; then
15650+
for ac_func in _configthreadlocale
15651+
do :
15652+
ac_fn_c_check_func "$LINENO" "_configthreadlocale" "ac_cv_func__configthreadlocale"
15653+
if test "x$ac_cv_func__configthreadlocale" = xyes; then :
15654+
cat >>confdefs.h <<_ACEOF
15655+
#define HAVE__CONFIGTHREADLOCALE 1
15656+
_ACEOF
15657+
15658+
fi
15659+
done
15660+
1565015661
ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
1565115662
if test "x$ac_cv_func_gettimeofday" = xyes; then :
1565215663
$as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h

‎configure.in

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,31 @@ PGAC_FUNC_WCSTOMBS_L
15681568
LIBS_including_readline="$LIBS"
15691569
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
15701570

1571-
AC_CHECK_FUNCS([cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range utime utimes wcstombs_l])
1571+
AC_CHECK_FUNCS(m4_normalize([
1572+
cbrt
1573+
clock_gettime
1574+
dlopen
1575+
fdatasync
1576+
getifaddrs
1577+
getpeerucred
1578+
getrlimit
1579+
mbstowcs_l
1580+
memmove
1581+
poll
1582+
posix_fallocate
1583+
pstat
1584+
pthread_is_threaded_np
1585+
readlink
1586+
setproctitle
1587+
setsid
1588+
shm_open
1589+
symlink
1590+
sync_file_range
1591+
uselocale
1592+
utime
1593+
utimes
1594+
wcstombs_l
1595+
]))
15721596

15731597
AC_REPLACE_FUNCS(fseeko)
15741598
case $host_os in
@@ -1732,6 +1756,7 @@ fi
17321756

17331757
# Win32 (really MinGW) support
17341758
if test "$PORTNAME" = "win32"; then
1759+
AC_CHECK_FUNCS(_configthreadlocale)
17351760
AC_REPLACE_FUNCS(gettimeofday)
17361761
AC_LIBOBJ(dirmod)
17371762
AC_LIBOBJ(kill)

‎src/include/pg_config.h.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,9 @@
677677
/* Define to 1 if the system has the type `unsigned long long int'. */
678678
#undef HAVE_UNSIGNED_LONG_LONG_INT
679679

680+
/* Define to 1 if you have the `uselocale' function. */
681+
#undef HAVE_USELOCALE
682+
680683
/* Define to 1 if you have the `utime' function. */
681684
#undef HAVE_UTIME
682685

@@ -743,6 +746,9 @@
743746
/* Define to 1 if your compiler understands __builtin_unreachable. */
744747
#undef HAVE__BUILTIN_UNREACHABLE
745748

749+
/* Define to 1 if you have the `_configthreadlocale' function. */
750+
#undef HAVE__CONFIGTHREADLOCALE
751+
746752
/* Define to 1 if you have __cpuid. */
747753
#undef HAVE__CPUID
748754

‎src/include/pg_config.h.win32

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,9 @@
541541
/* Define to 1 if you have the `unsetenv' function. */
542542
/* #undef HAVE_UNSETENV */
543543

544+
/* Define to 1 if you have the `uselocale' function. */
545+
/* #undef HAVE_USELOCALE */
546+
544547
/* Define to 1 if you have the `utime' function. */
545548
#define HAVE_UTIME 1
546549

@@ -592,6 +595,9 @@
592595
/* Define to 1 if your compiler understands __builtin_unreachable. */
593596
/* #undef HAVE__BUILTIN_UNREACHABLE */
594597

598+
/* Define to 1 if you have the `_configthreadlocale' function. */
599+
#define HAVE__CONFIGTHREADLOCALE 1
600+
595601
/* Define to 1 if you have __cpuid. */
596602
#define HAVE__CPUID 1
597603

‎src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -483,22 +483,45 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
483483
if (data_var.type!=ECPGt_EORT)
484484
{
485485
structstatementstmt;
486-
char*oldlocale;
486+
487+
memset(&stmt,0,sizeofstmt);
488+
stmt.lineno=lineno;
487489

488490
/* Make sure we do NOT honor the locale for numeric input */
489491
/* since the database gives the standard decimal point */
490-
oldlocale=ecpg_strdup(setlocale(LC_NUMERIC,NULL),lineno);
492+
/* (see comments in execute.c) */
493+
#ifdefHAVE_USELOCALE
494+
stmt.clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
495+
if (stmt.clocale!= (locale_t)0)
496+
stmt.oldlocale=uselocale(stmt.clocale);
497+
#else
498+
#ifdefHAVE__CONFIGTHREADLOCALE
499+
stmt.oldthreadlocale=_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
500+
#endif
501+
stmt.oldlocale=ecpg_strdup(setlocale(LC_NUMERIC,NULL),lineno);
491502
setlocale(LC_NUMERIC,"C");
492-
493-
memset(&stmt,0,sizeofstmt);
494-
stmt.lineno=lineno;
503+
#endif
495504

496505
/* desperate try to guess something sensible */
497506
stmt.connection=ecpg_get_connection(NULL);
498507
ecpg_store_result(ECPGresult,index,&stmt,&data_var);
499508

500-
setlocale(LC_NUMERIC,oldlocale);
501-
ecpg_free(oldlocale);
509+
#ifdefHAVE_USELOCALE
510+
if (stmt.oldlocale!= (locale_t)0)
511+
uselocale(stmt.oldlocale);
512+
if (stmt.clocale)
513+
freelocale(stmt.clocale);
514+
#else
515+
if (stmt.oldlocale)
516+
{
517+
setlocale(LC_NUMERIC,stmt.oldlocale);
518+
ecpg_free(stmt.oldlocale);
519+
}
520+
#ifdefHAVE__CONFIGTHREADLOCALE
521+
if (stmt.oldthreadlocale!=-1)
522+
_configthreadlocale(stmt.oldthreadlocale);
523+
#endif
524+
#endif
502525
}
503526
elseif (data_var.ind_type!=ECPGt_NO_INDICATOR&&data_var.ind_pointer!=NULL)
504527

‎src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,12 @@ free_statement(struct statement *stmt)
103103
free_variable(stmt->outlist);
104104
ecpg_free(stmt->command);
105105
ecpg_free(stmt->name);
106+
#ifdefHAVE_USELOCALE
107+
if (stmt->clocale)
108+
freelocale(stmt->clocale);
109+
#else
106110
ecpg_free(stmt->oldlocale);
111+
#endif
107112
ecpg_free(stmt);
108113
}
109114

@@ -1778,15 +1783,40 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
17781783

17791784
/*
17801785
* Make sure we do NOT honor the locale for numeric input/output since the
1781-
* database wants the standard decimal point
1786+
* database wants the standard decimal point. If available, use
1787+
* uselocale() for this because it's thread-safe. Windows doesn't have
1788+
* that, but it usually does have _configthreadlocale().
17821789
*/
1790+
#ifdefHAVE_USELOCALE
1791+
stmt->clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
1792+
if (stmt->clocale== (locale_t)0)
1793+
{
1794+
ecpg_do_epilogue(stmt);
1795+
return false;
1796+
}
1797+
stmt->oldlocale=uselocale(stmt->clocale);
1798+
if (stmt->oldlocale== (locale_t)0)
1799+
{
1800+
ecpg_do_epilogue(stmt);
1801+
return false;
1802+
}
1803+
#else
1804+
#ifdefHAVE__CONFIGTHREADLOCALE
1805+
stmt->oldthreadlocale=_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1806+
if (stmt->oldthreadlocale==-1)
1807+
{
1808+
ecpg_do_epilogue(stmt);
1809+
return false;
1810+
}
1811+
#endif
17831812
stmt->oldlocale=ecpg_strdup(setlocale(LC_NUMERIC,NULL),lineno);
17841813
if (stmt->oldlocale==NULL)
17851814
{
17861815
ecpg_do_epilogue(stmt);
17871816
return false;
17881817
}
17891818
setlocale(LC_NUMERIC,"C");
1819+
#endif
17901820

17911821
#ifdefENABLE_THREAD_SAFETY
17921822
ecpg_pthreads_init();
@@ -1989,8 +2019,18 @@ ecpg_do_epilogue(struct statement *stmt)
19892019
if (stmt==NULL)
19902020
return;
19912021

2022+
#ifdefHAVE_USELOCALE
2023+
if (stmt->oldlocale!= (locale_t)0)
2024+
uselocale(stmt->oldlocale);
2025+
#else
19922026
if (stmt->oldlocale)
2027+
{
19932028
setlocale(LC_NUMERIC,stmt->oldlocale);
2029+
#ifdefHAVE__CONFIGTHREADLOCALE
2030+
_configthreadlocale(stmt->oldthreadlocale);
2031+
#endif
2032+
}
2033+
#endif
19942034

19952035
free_statement(stmt);
19962036
}

‎src/interfaces/ecpg/ecpglib/extern.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#ifndefCHAR_BIT
1313
#include<limits.h>
1414
#endif
15+
#ifdefLOCALE_T_IN_XLOCALE
16+
#include<xlocale.h>
17+
#endif
1518

1619
enumCOMPAT_MODE
1720
{
@@ -61,7 +64,15 @@ struct statement
6164
boolquestionmarks;
6265
structvariable*inlist;
6366
structvariable*outlist;
67+
#ifdefHAVE_USELOCALE
68+
locale_tclocale;
69+
locale_toldlocale;
70+
#else
6471
char*oldlocale;
72+
#ifdefHAVE__CONFIGTHREADLOCALE
73+
intoldthreadlocale;
74+
#endif
75+
#endif
6576
intnparams;
6677
char**paramvalues;
6778
PGresult*results;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp