diff options
-rw-r--r-- | cygwin/cygwin.c | 41 | ||||
-rw-r--r-- | locale.c | 15 | ||||
-rw-r--r-- | perl.h | 5 | ||||
-rw-r--r-- | pod/perldelta.pod | 5 |
4 files changed, 60 insertions, 6 deletions
diff --git a/cygwin/cygwin.c b/cygwin/cygwin.c index 59aa730448..24b278f2fd 100644 --- a/cygwin/cygwin.c +++ b/cygwin/cygwin.c @@ -154,7 +154,15 @@ wide_to_utf8(const wchar_t *wbuf) { char *buf; int wlen = 0; - char *oldlocale = setlocale(LC_CTYPE, NULL); + char *oldlocale; + dVAR; + + /* Here and elsewhere in this file, we have a critical section to prevent + * another thread from changing the locale out from under us. XXX But why + * not just use uvchr_to_utf8? */ + LOCALE_LOCK; + + oldlocale = setlocale(LC_CTYPE, NULL); setlocale(LC_CTYPE, "utf-8"); /* uvchr_to_utf8(buf, chr) or Encoding::_bytes_to_utf8(sv, "UCS-2BE"); */ @@ -164,6 +172,9 @@ wide_to_utf8(const wchar_t *wbuf) if (oldlocale) setlocale(LC_CTYPE, oldlocale); else setlocale(LC_CTYPE, "C"); + + LOCALE_UNLOCK; + return buf; } @@ -172,8 +183,13 @@ utf8_to_wide(const char *buf) { wchar_t *wbuf; mbstate_t mbs; - char *oldlocale = setlocale(LC_CTYPE, NULL); + char *oldlocale; int wlen = sizeof(wchar_t)*strlen(buf); + dVAR; + + LOCALE_LOCK; + + oldlocale = setlocale(LC_CTYPE, NULL); setlocale(LC_CTYPE, "utf-8"); wbuf = (wchar_t *) safemalloc(wlen); @@ -182,6 +198,9 @@ utf8_to_wide(const char *buf) if (oldlocale) setlocale(LC_CTYPE, oldlocale); else setlocale(LC_CTYPE, "C"); + + LOCALE_UNLOCK; + return wbuf; } #endif /* cygwin 1.7 */ @@ -280,7 +299,12 @@ XS(XS_Cygwin_win_to_posix_path) wchar_t *wbuf = (wchar_t *) safemalloc(wlen); if (!IN_BYTES) { mbstate_t mbs; - char *oldlocale = setlocale(LC_CTYPE, NULL); + char *oldlocale; + dVAR; + + LOCALE_LOCK; + + oldlocale = setlocale(LC_CTYPE, NULL); setlocale(LC_CTYPE, "utf-8"); /* utf8_to_uvchr_buf(src_path, src_path + wlen, wpath) or Encoding::_utf8_to_bytes(sv, "UCS-2BE"); */ wlen = mbsrtowcs(wpath, (const char**)&src_path, wlen, &mbs); @@ -288,6 +312,8 @@ XS(XS_Cygwin_win_to_posix_path) err = cygwin_conv_path(what, wpath, wbuf, wlen); if (oldlocale) setlocale(LC_CTYPE, oldlocale); else setlocale(LC_CTYPE, "C"); + + LOCALE_UNLOCK; } else { /* use bytes; assume already ucs-2 encoded bytestream */ err = cygwin_conv_path(what, src_path, wbuf, wlen); } @@ -365,7 +391,12 @@ XS(XS_Cygwin_posix_to_win_path) int wlen = sizeof(wchar_t)*(len + 260 + 1001); wchar_t *wpath = (wchar_t *) safemalloc(sizeof(wchar_t)*len); wchar_t *wbuf = (wchar_t *) safemalloc(wlen); - char *oldlocale = setlocale(LC_CTYPE, NULL); + char *oldlocale; + dVAR; + + LOCALE_LOCK; + + oldlocale = setlocale(LC_CTYPE, NULL); setlocale(LC_CTYPE, "utf-8"); if (!IN_BYTES) { mbstate_t mbs; @@ -388,6 +419,8 @@ XS(XS_Cygwin_posix_to_win_path) wcsrtombs(win_path, (const wchar_t **)&wbuf, wlen, NULL); if (oldlocale) setlocale(LC_CTYPE, oldlocale); else setlocale(LC_CTYPE, "C"); + + LOCALE_UNLOCK; } else { int what = absolute_flag ? CCP_POSIX_TO_WIN_A : CCP_POSIX_TO_WIN_A | CCP_RELATIVE; win_path = (char *) safemalloc(len + 260 + 1001); @@ -1809,13 +1809,21 @@ Perl__is_in_locale_category(pTHX_ const bool compiling, const int category) char * Perl_my_strerror(pTHX_ const int errnum) { + dVAR; /* Uses C locale for the error text unless within scope of 'use locale' for * LC_MESSAGES */ #ifdef USE_LOCALE_MESSAGES if (! IN_LC(LC_MESSAGES)) { - char * save_locale = setlocale(LC_MESSAGES, NULL); + char * save_locale; + + /* We have a critical section to prevent another thread from changing + * the locale out from under us (or zapping the buffer returned from + * setlocale() ) */ + LOCALE_LOCK; + + save_locale = setlocale(LC_MESSAGES, NULL); if (! isNAME_C_OR_POSIX(save_locale)) { char *errstr; @@ -1830,8 +1838,13 @@ Perl_my_strerror(pTHX_ const int errnum) { setlocale(LC_MESSAGES, save_locale); Safefree(save_locale); + + LOCALE_UNLOCK; + return errstr; } + + LOCALE_UNLOCK; } #endif @@ -5958,6 +5958,9 @@ typedef struct am_table_short AMTS; # define LOCALE_INIT MUTEX_INIT(&PL_locale_mutex) # define LOCALE_TERM MUTEX_DESTROY(&PL_locale_mutex) +# define LOCALE_LOCK MUTEX_LOCK(&PL_locale_mutex) +# define LOCALE_UNLOCK MUTEX_UNLOCK(&PL_locale_mutex) + /* Returns TRUE if the plain locale pragma without a parameter is in effect */ # define IN_LOCALE_RUNTIME cBOOL(CopHINTS_get(PL_curcop) & HINT_LOCALE) @@ -6043,6 +6046,8 @@ typedef struct am_table_short AMTS; #else /* No locale usage */ # define LOCALE_INIT # define LOCALE_TERM +# define LOCALE_LOCK +# define LOCALE_UNLOCK # define IN_LOCALE_RUNTIME 0 # define IN_SOME_LOCALE_FORM_RUNTIME 0 # define IN_LOCALE_COMPILETIME 0 diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 57cf7c1daa..4dcc7af6f5 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -341,7 +341,10 @@ files in F<ext/> and F<lib/> are best summarized in L</Modules and Pragmata>. =item * -XXX +A race condition which occurred when computing C<"$!"> with threads +activated has been fixed. This showed up only on Darwin platforms. A +related problem on Cygwin platforms involving UTF-8 strings has also +been fixed. [perl #127708] =back |