summaryrefslogtreecommitdiff
path: root/libguile/strings.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2012-02-14 14:30:48 +0100
committerAndy Wingo <wingo@pobox.com>2012-02-17 12:11:35 +0100
commit8dfb7bbfd908ca883d0fdd0d868e13e6b20803ae (patch)
treea9de6d013851758e47cab732e79039b51c44187a /libguile/strings.c
parent6a97b1f93aace5c7c976aef51d36b3ae9cfd5630 (diff)
downloadguile-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.c25
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"
}