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

Commit8eb4a93

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.This should get back-patched, but let's see what the buildfarmthinks of it first.Michael Meskes and Tom Lane; thanks also to Takayuki Tsunakawa.Discussion:https://postgr.es/m/31420.1547783697@sss.pgh.pa.us
1 parentf4593bd commit8eb4a93

File tree

7 files changed

+90
-9
lines changed

7 files changed

+90
-9
lines changed

‎configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15209,7 +15209,7 @@ fi
1520915209
LIBS_including_readline="$LIBS"
1521015210
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
1521115211

15212-
for ac_func in cbrt clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_range utime utimes wcstombs_l
15212+
for ac_func in cbrt clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink sync_file_rangeuselocaleutime utimes wcstombs_l
1521315213
do :
1521415214
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1521515215
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

‎configure.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,7 @@ AC_CHECK_FUNCS(m4_normalize([
16181618
strsignal
16191619
symlink
16201620
sync_file_range
1621+
uselocale
16211622
utime
16221623
utimes
16231624
wcstombs_l

‎src/include/pg_config.h.in

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

694+
/* Define to 1 if you have the `uselocale' function. */
695+
#undef HAVE_USELOCALE
696+
694697
/* Define to 1 if you have the `utime' function. */
695698
#undef HAVE_UTIME
696699

‎src/include/pg_config.h.win32

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,9 @@
545545
/* Define to 1 if you have the `unsetenv' function. */
546546
/* #undef HAVE_UNSETENV */
547547

548+
/* Define to 1 if you have the `uselocale' function. */
549+
/* #undef HAVE_USELOCALE */
550+
548551
/* Define to 1 if you have the `utime' function. */
549552
#define HAVE_UTIME 1
550553

‎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+
#ifdefWIN32
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+
#ifdefWIN32
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/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+
#ifdefWIN32
73+
intoldthreadlocale;
74+
#endif
75+
#endif
6576
intnparams;
6677
char**paramvalues;
6778
PGresult*results;

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

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

@@ -1771,15 +1776,40 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
17711776

17721777
/*
17731778
* Make sure we do NOT honor the locale for numeric input/output since the
1774-
* database wants the standard decimal point
1779+
* database wants the standard decimal point. If available, use
1780+
* uselocale() for this because it's thread-safe. Windows doesn't have
1781+
* that, but it does have _configthreadlocale().
17751782
*/
1783+
#ifdefHAVE_USELOCALE
1784+
stmt->clocale=newlocale(LC_NUMERIC_MASK,"C", (locale_t)0);
1785+
if (stmt->clocale== (locale_t)0)
1786+
{
1787+
ecpg_do_epilogue(stmt);
1788+
return false;
1789+
}
1790+
stmt->oldlocale=uselocale(stmt->clocale);
1791+
if (stmt->oldlocale== (locale_t)0)
1792+
{
1793+
ecpg_do_epilogue(stmt);
1794+
return false;
1795+
}
1796+
#else
1797+
#ifdefWIN32
1798+
stmt->oldthreadlocale=_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
1799+
if (stmt->oldthreadlocale==-1)
1800+
{
1801+
ecpg_do_epilogue(stmt);
1802+
return false;
1803+
}
1804+
#endif
17761805
stmt->oldlocale=ecpg_strdup(setlocale(LC_NUMERIC,NULL),lineno);
17771806
if (stmt->oldlocale==NULL)
17781807
{
17791808
ecpg_do_epilogue(stmt);
17801809
return false;
17811810
}
17821811
setlocale(LC_NUMERIC,"C");
1812+
#endif
17831813

17841814
#ifdefENABLE_THREAD_SAFETY
17851815
ecpg_pthreads_init();
@@ -1982,8 +2012,18 @@ ecpg_do_epilogue(struct statement *stmt)
19822012
if (stmt==NULL)
19832013
return;
19842014

2015+
#ifdefHAVE_USELOCALE
2016+
if (stmt->oldlocale!= (locale_t)0)
2017+
uselocale(stmt->oldlocale);
2018+
#else
19852019
if (stmt->oldlocale)
2020+
{
19862021
setlocale(LC_NUMERIC,stmt->oldlocale);
2022+
#ifdefWIN32
2023+
_configthreadlocale(stmt->oldthreadlocale);
2024+
#endif
2025+
}
2026+
#endif
19872027

19882028
free_statement(stmt);
19892029
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp