mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
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.
This commit is contained in:
parent
6a97b1f93a
commit
8dfb7bbfd9
4 changed files with 45 additions and 1 deletions
|
@ -1934,10 +1934,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
|
||||||
c_strlen = scm_i_string_length (str); \
|
c_strlen = scm_i_string_length (str); \
|
||||||
if (scm_i_is_narrow_string (str)) \
|
if (scm_i_is_narrow_string (str)) \
|
||||||
{ \
|
{ \
|
||||||
|
scm_i_lock_iconv (); \
|
||||||
err = mem_iconveh (scm_i_string_chars (str), c_strlen, \
|
err = mem_iconveh (scm_i_string_chars (str), c_strlen, \
|
||||||
"ISO-8859-1", c_utf_name, \
|
"ISO-8859-1", c_utf_name, \
|
||||||
iconveh_question_mark, NULL, \
|
iconveh_question_mark, NULL, \
|
||||||
&c_utf, &c_utf_len); \
|
&c_utf, &c_utf_len); \
|
||||||
|
scm_i_unlock_iconv (); \
|
||||||
if (SCM_UNLIKELY (err)) \
|
if (SCM_UNLIKELY (err)) \
|
||||||
scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \
|
scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \
|
||||||
scm_list_1 (str), err); \
|
scm_list_1 (str), err); \
|
||||||
|
@ -1945,10 +1947,12 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
const scm_t_wchar *wbuf = scm_i_string_wide_chars (str); \
|
const scm_t_wchar *wbuf = scm_i_string_wide_chars (str); \
|
||||||
|
scm_i_lock_iconv (); \
|
||||||
c_utf = u32_conv_to_encoding (c_utf_name, \
|
c_utf = u32_conv_to_encoding (c_utf_name, \
|
||||||
iconveh_question_mark, \
|
iconveh_question_mark, \
|
||||||
(scm_t_uint32 *) wbuf, \
|
(scm_t_uint32 *) wbuf, \
|
||||||
c_strlen, NULL, NULL, &c_utf_len); \
|
c_strlen, NULL, NULL, &c_utf_len); \
|
||||||
|
scm_i_unlock_iconv (); \
|
||||||
if (SCM_UNLIKELY (c_utf == NULL)) \
|
if (SCM_UNLIKELY (c_utf == NULL)) \
|
||||||
scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \
|
scm_syserror_msg (FUNC_NAME, "failed to convert string: ~A", \
|
||||||
scm_list_1 (str), errno); \
|
scm_list_1 (str), errno); \
|
||||||
|
@ -2050,10 +2054,12 @@ SCM_DEFINE (scm_string_to_utf32, "string->utf32",
|
||||||
c_utf = (char *) SCM_BYTEVECTOR_CONTENTS (utf); \
|
c_utf = (char *) SCM_BYTEVECTOR_CONTENTS (utf); \
|
||||||
utf_encoding_name (c_utf_name, (_utf_width), endianness); \
|
utf_encoding_name (c_utf_name, (_utf_width), endianness); \
|
||||||
\
|
\
|
||||||
|
scm_i_lock_iconv (); \
|
||||||
err = mem_iconveh (c_utf, c_utf_len, \
|
err = mem_iconveh (c_utf, c_utf_len, \
|
||||||
c_utf_name, "UTF-8", \
|
c_utf_name, "UTF-8", \
|
||||||
iconveh_question_mark, NULL, \
|
iconveh_question_mark, NULL, \
|
||||||
&c_str, &c_strlen); \
|
&c_str, &c_strlen); \
|
||||||
|
scm_i_unlock_iconv (); \
|
||||||
if (SCM_UNLIKELY (err)) \
|
if (SCM_UNLIKELY (err)) \
|
||||||
scm_syserror_msg (FUNC_NAME, "failed to convert to string: ~A", \
|
scm_syserror_msg (FUNC_NAME, "failed to convert to string: ~A", \
|
||||||
scm_list_1 (utf), err); \
|
scm_list_1 (utf), err); \
|
||||||
|
|
|
@ -882,7 +882,9 @@ open_iconv_descriptors (const char *encoding, int reading, int writing)
|
||||||
allocation. */
|
allocation. */
|
||||||
scm_gc_register_allocation (16 * 1024);
|
scm_gc_register_allocation (16 * 1024);
|
||||||
|
|
||||||
|
scm_i_lock_iconv ();
|
||||||
input_cd = iconv_open ("UTF-8", encoding);
|
input_cd = iconv_open ("UTF-8", encoding);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
if (input_cd == (iconv_t) -1)
|
if (input_cd == (iconv_t) -1)
|
||||||
goto invalid_encoding;
|
goto invalid_encoding;
|
||||||
}
|
}
|
||||||
|
@ -893,11 +895,15 @@ open_iconv_descriptors (const char *encoding, int reading, int writing)
|
||||||
allocation. */
|
allocation. */
|
||||||
scm_gc_register_allocation (16 * 1024);
|
scm_gc_register_allocation (16 * 1024);
|
||||||
|
|
||||||
|
scm_i_lock_iconv ();
|
||||||
output_cd = iconv_open (encoding, "UTF-8");
|
output_cd = iconv_open (encoding, "UTF-8");
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
if (output_cd == (iconv_t) -1)
|
if (output_cd == (iconv_t) -1)
|
||||||
{
|
{
|
||||||
|
scm_i_lock_iconv ();
|
||||||
if (input_cd != (iconv_t) -1)
|
if (input_cd != (iconv_t) -1)
|
||||||
iconv_close (input_cd);
|
iconv_close (input_cd);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
goto invalid_encoding;
|
goto invalid_encoding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -930,10 +936,12 @@ open_iconv_descriptors (const char *encoding, int reading, int writing)
|
||||||
static void
|
static void
|
||||||
close_iconv_descriptors (scm_t_iconv_descriptors *id)
|
close_iconv_descriptors (scm_t_iconv_descriptors *id)
|
||||||
{
|
{
|
||||||
|
scm_i_lock_iconv ();
|
||||||
if (id->input_cd != (iconv_t) -1)
|
if (id->input_cd != (iconv_t) -1)
|
||||||
iconv_close (id->input_cd);
|
iconv_close (id->input_cd);
|
||||||
if (id->output_cd != (iconv_t) -1)
|
if (id->output_cd != (iconv_t) -1)
|
||||||
iconv_close (id->output_cd);
|
iconv_close (id->output_cd);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
id->input_cd = (void *) -1;
|
id->input_cd = (void *) -1;
|
||||||
id->output_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";
|
encoding = "ISO-8859-1";
|
||||||
|
|
||||||
len = sizeof (result_buf);
|
len = sizeof (result_buf);
|
||||||
|
scm_i_lock_iconv ();
|
||||||
result = u32_conv_to_encoding (encoding,
|
result = u32_conv_to_encoding (encoding,
|
||||||
(enum iconv_ilseq_handler) pt->ilseq_handler,
|
(enum iconv_ilseq_handler) pt->ilseq_handler,
|
||||||
(uint32_t *) &c, 1, NULL,
|
(uint32_t *) &c, 1, NULL,
|
||||||
result_buf, &len);
|
result_buf, &len);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
|
|
||||||
if (SCM_UNLIKELY (result == NULL || len == 0))
|
if (SCM_UNLIKELY (result == NULL || len == 0))
|
||||||
scm_encoding_error (FUNC_NAME, errno,
|
scm_encoding_error (FUNC_NAME, errno,
|
||||||
|
|
|
@ -225,9 +225,25 @@ narrow_stringbuf (SCM buf)
|
||||||
return new_buf;
|
return new_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
scm_i_pthread_mutex_t stringbuf_write_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
scm_i_pthread_mutex_t stringbuf_write_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
||||||
SCM_PTHREAD_ATFORK_LOCK_STATIC_MUTEX (stringbuf_write_mutex);
|
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.
|
/* 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);
|
return scm_from_utf8_stringn (str, len);
|
||||||
|
|
||||||
u32len = 0;
|
u32len = 0;
|
||||||
|
scm_i_lock_iconv ();
|
||||||
u32 = (scm_t_wchar *) u32_conv_from_encoding (encoding,
|
u32 = (scm_t_wchar *) u32_conv_from_encoding (encoding,
|
||||||
(enum iconv_ilseq_handler)
|
(enum iconv_ilseq_handler)
|
||||||
handler,
|
handler,
|
||||||
str, len,
|
str, len,
|
||||||
NULL,
|
NULL,
|
||||||
NULL, &u32len);
|
NULL, &u32len);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
|
|
||||||
if (SCM_UNLIKELY (u32 == NULL))
|
if (SCM_UNLIKELY (u32 == NULL))
|
||||||
decoding_error (__func__, errno, str, len);
|
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";
|
enc = "ISO-8859-1";
|
||||||
if (scm_i_is_narrow_string (str))
|
if (scm_i_is_narrow_string (str))
|
||||||
{
|
{
|
||||||
|
scm_i_lock_iconv ();
|
||||||
ret = mem_iconveh (scm_i_string_chars (str), ilen,
|
ret = mem_iconveh (scm_i_string_chars (str), ilen,
|
||||||
"ISO-8859-1", enc,
|
"ISO-8859-1", enc,
|
||||||
(enum iconv_ilseq_handler) handler, NULL,
|
(enum iconv_ilseq_handler) handler, NULL,
|
||||||
&buf, &len);
|
&buf, &len);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
scm_encoding_error (__func__, errno,
|
scm_encoding_error (__func__, errno,
|
||||||
|
@ -2085,12 +2105,14 @@ scm_to_stringn (SCM str, size_t *lenp, const char *encoding,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
scm_i_lock_iconv ();
|
||||||
buf = u32_conv_to_encoding (enc,
|
buf = u32_conv_to_encoding (enc,
|
||||||
(enum iconv_ilseq_handler) handler,
|
(enum iconv_ilseq_handler) handler,
|
||||||
(scm_t_uint32 *) scm_i_string_wide_chars (str),
|
(scm_t_uint32 *) scm_i_string_wide_chars (str),
|
||||||
ilen,
|
ilen,
|
||||||
NULL,
|
NULL,
|
||||||
NULL, &len);
|
NULL, &len);
|
||||||
|
scm_i_unlock_iconv ();
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
scm_encoding_error (__func__, errno,
|
scm_encoding_error (__func__, errno,
|
||||||
"cannot convert wide string to output locale",
|
"cannot convert wide string to output locale",
|
||||||
|
@ -2334,6 +2356,9 @@ scm_init_strings ()
|
||||||
{
|
{
|
||||||
scm_nullstr = scm_i_make_string (0, NULL, 0);
|
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"
|
#include "libguile/strings.x"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#ifndef SCM_STRINGS_H
|
#ifndef SCM_STRINGS_H
|
||||||
#define 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* 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. */
|
/* 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 char **scm_i_allocate_string_pointers (SCM list);
|
||||||
SCM_INTERNAL void scm_i_get_substring_spec (size_t len,
|
SCM_INTERNAL void scm_i_get_substring_spec (size_t len,
|
||||||
SCM start, size_t *cstart,
|
SCM start, size_t *cstart,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue