summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/bytevectors.c6
-rw-r--r--libguile/ports.c10
-rw-r--r--libguile/strings.c25
-rw-r--r--libguile/strings.h5
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,