diff options
-rw-r--r-- | libguile/bytevectors.c | 6 | ||||
-rw-r--r-- | libguile/ports.c | 10 | ||||
-rw-r--r-- | libguile/strings.c | 25 | ||||
-rw-r--r-- | libguile/strings.h | 5 |
4 files changed, 45 insertions, 1 deletions
diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c index 668c46d17..6ea60f823 100644 --- a/libguile/bytevectors.c +++ b/libguile/bytevectors.c @@ -1934,10 +1934,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness) c_strlen = scm_i_string_length (str); \ if (scm_i_is_narrow_string (str)) \ { \ + scm_i_lock_iconv (); \ err = mem_iconveh (scm_i_string_chars (str), c_strlen, \ "ISO-8859-1", c_utf_name, \ iconveh_question_mark, NULL, \ &c_utf, &c_utf_len); \ + scm_i_unlock_iconv (); \ if (SCM_UNLIKELY (err)) \ scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \ scm_list_1 (str), err); \ @@ -1945,10 +1947,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness) else \ { \ const scm_t_wchar *wbuf = scm_i_string_wide_chars (str); \ + scm_i_lock_iconv (); \ c_utf = u32_conv_to_encoding (c_utf_name, \ iconveh_question_mark, \ (scm_t_uint32 *) wbuf, \ c_strlen, NULL, NULL, &c_utf_len); \ + scm_i_unlock_iconv (); \ if (SCM_UNLIKELY (c_utf == NULL)) \ scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \ scm_list_1 (str), errno); \ @@ -2050,10 +2054,12 @@ SCM_DEFINE (scm_string_to_utf32, "string->utf32", c_utf = (char *) SCM_BYTEVECTOR_CONTENTS (utf); \ utf_encoding_name (c_utf_name, (_utf_width), endianness); \ \ + scm_i_lock_iconv (); \ err = mem_iconveh (c_utf, c_utf_len, \ c_utf_name, "UTF-8", \ iconveh_question_mark, NULL, \ &c_str, &c_strlen); \ + scm_i_unlock_iconv (); \ if (SCM_UNLIKELY (err)) \ scm_syserror_msg (FUNC_NAME, "failed to convert to string: ~A", \ scm_list_1 (utf), err); \ diff --git a/libguile/ports.c b/libguile/ports.c index 18607514c..414ea9400 100644 --- a/libguile/ports.c +++ b/libguile/ports.c @@ -882,7 +882,9 @@ open_iconv_descriptors (const char *encoding, int reading, int writing) allocation. */ scm_gc_register_allocation (16 * 1024); + scm_i_lock_iconv (); input_cd = iconv_open ("UTF-8", encoding); + scm_i_unlock_iconv (); if (input_cd == (iconv_t) -1) goto invalid_encoding; } @@ -893,11 +895,15 @@ open_iconv_descriptors (const char *encoding, int reading, int writing) allocation. */ scm_gc_register_allocation (16 * 1024); + scm_i_lock_iconv (); output_cd = iconv_open (encoding, "UTF-8"); + scm_i_unlock_iconv (); if (output_cd == (iconv_t) -1) { + scm_i_lock_iconv (); if (input_cd != (iconv_t) -1) iconv_close (input_cd); + scm_i_unlock_iconv (); goto invalid_encoding; } } @@ -930,10 +936,12 @@ open_iconv_descriptors (const char *encoding, int reading, int writing) static void close_iconv_descriptors (scm_t_iconv_descriptors *id) { + scm_i_lock_iconv (); if (id->input_cd != (iconv_t) -1) iconv_close (id->input_cd); if (id->output_cd != (iconv_t) -1) iconv_close (id->output_cd); + scm_i_unlock_iconv (); id->input_cd = (void *) -1; id->output_cd = (void *) -1; } @@ -1937,10 +1945,12 @@ scm_ungetc_unlocked (scm_t_wchar c, SCM port) encoding = "ISO-8859-1"; len = sizeof (result_buf); + scm_i_lock_iconv (); result = u32_conv_to_encoding (encoding, (enum iconv_ilseq_handler) pt->ilseq_handler, (uint32_t *) &c, 1, NULL, result_buf, &len); + scm_i_unlock_iconv (); if (SCM_UNLIKELY (result == NULL || len == 0)) scm_encoding_error (FUNC_NAME, errno, diff --git a/libguile/strings.c b/libguile/strings.c index c2edcd70a..977548b74 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -225,9 +225,25 @@ narrow_stringbuf (SCM buf) return new_buf; } + + scm_i_pthread_mutex_t stringbuf_write_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER; SCM_PTHREAD_ATFORK_LOCK_STATIC_MUTEX (stringbuf_write_mutex); +static scm_i_pthread_mutex_t iconv_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER; + +void +scm_i_lock_iconv (void) +{ + scm_i_pthread_mutex_lock (&iconv_mutex); +} + +void +scm_i_unlock_iconv (void) +{ + scm_i_pthread_mutex_unlock (&iconv_mutex); +} + /* Copy-on-write strings. */ @@ -1531,12 +1547,14 @@ scm_from_stringn (const char *str, size_t len, const char *encoding, return scm_from_utf8_stringn (str, len); u32len = 0; + scm_i_lock_iconv (); u32 = (scm_t_wchar *) u32_conv_from_encoding (encoding, (enum iconv_ilseq_handler) handler, str, len, NULL, NULL, &u32len); + scm_i_unlock_iconv (); if (SCM_UNLIKELY (u32 == NULL)) decoding_error (__func__, errno, str, len); @@ -2071,10 +2089,12 @@ scm_to_stringn (SCM str, size_t *lenp, const char *encoding, enc = "ISO-8859-1"; if (scm_i_is_narrow_string (str)) { + scm_i_lock_iconv (); ret = mem_iconveh (scm_i_string_chars (str), ilen, "ISO-8859-1", enc, (enum iconv_ilseq_handler) handler, NULL, &buf, &len); + scm_i_unlock_iconv (); if (ret != 0) scm_encoding_error (__func__, errno, @@ -2085,12 +2105,14 @@ scm_to_stringn (SCM str, size_t *lenp, const char *encoding, } else { + scm_i_lock_iconv (); buf = u32_conv_to_encoding (enc, (enum iconv_ilseq_handler) handler, (scm_t_uint32 *) scm_i_string_wide_chars (str), ilen, NULL, NULL, &len); + scm_i_unlock_iconv (); if (buf == NULL) scm_encoding_error (__func__, errno, "cannot convert wide string to output locale", @@ -2334,6 +2356,9 @@ scm_init_strings () { scm_nullstr = scm_i_make_string (0, NULL, 0); + scm_i_pthread_atfork (scm_i_lock_iconv, scm_i_unlock_iconv, + scm_i_unlock_iconv); + #include "libguile/strings.x" } diff --git a/libguile/strings.h b/libguile/strings.h index 04a976211..b88e97c47 100644 --- a/libguile/strings.h +++ b/libguile/strings.h @@ -3,7 +3,7 @@ #ifndef SCM_STRINGS_H #define SCM_STRINGS_H -/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -220,6 +220,9 @@ SCM_INTERNAL void scm_decoding_error (const char *subr, int err, /* internal utility functions. */ +SCM_INTERNAL void scm_i_lock_iconv (void); +SCM_INTERNAL void scm_i_unlock_iconv (void); + SCM_INTERNAL char **scm_i_allocate_string_pointers (SCM list); SCM_INTERNAL void scm_i_get_substring_spec (size_t len, SCM start, size_t *cstart, |