diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-14 14:30:48 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-17 12:11:35 +0100 |
commit | 8dfb7bbfd908ca883d0fdd0d868e13e6b20803ae (patch) | |
tree | a9de6d013851758e47cab732e79039b51c44187a /libguile/strings.c | |
parent | 6a97b1f93aace5c7c976aef51d36b3ae9cfd5630 (diff) | |
download | guile-8dfb7bbfd908ca883d0fdd0d868e13e6b20803ae.tar.gz |
wrap iconv_open / iconv_close with a lock to help in thread/fork issues
* libguile/bytevectors.c (STRING_TO_UTF, scm_string_to_utf8)
(UTF_TO_STRING):
* libguile/ports.c (open_iconv_descriptors, close_iconv_descriptors):
* libguile/strings.c (scm_from_stringn, scm_to_stringn): Wrap operations
that acquire and destroy iconv contexts with a mutex. While iconv is
threadsafe, internally it uses a lock, and we need to make sure when
we fork() that no one has that lock -- so we surround it with another
one. Gross.
Diffstat (limited to 'libguile/strings.c')
-rw-r--r-- | libguile/strings.c | 25 |
1 files changed, 25 insertions, 0 deletions
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" } |