diff options
author | Andy Wingo <wingo@pobox.com> | 2016-05-23 16:37:23 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2016-05-23 16:37:23 +0200 |
commit | 6bf7ec0c9c615f0b3bbb03bae15ebb10194e2bf8 (patch) | |
tree | 4def6570ee24313f3feb973c7297479dd4bdf6b9 /libguile/print.c | |
parent | c95a19376b1f2fd26c60fb56c1c9892eef1acfc4 (diff) | |
download | guile-6bf7ec0c9c615f0b3bbb03bae15ebb10194e2bf8.tar.gz |
Thread-safety fixes for iconv and ports
* libguile/ports-internal.h (scm_t_port): Rework to store iconv
descriptors inline, so that the port finalizer doesn't race with the
iconv descriptor finalizer. Access is serialized through a lock.
Fixes a bug whereby if the port finalizer and the descriptor finalizer
run on different threads, the close-port run by the port finalizer
could try to free the iconv descriptors at the same time as the
descriptor finalizer.
* libguile/ports.c (iconv_lock): New static variable.
(scm_c_make_port_with_encoding): Initialize iconv-related fields.
(scm_close_port): Lock while frobbing iconv descriptors.
(prepare_iconv_descriptors): Adapt.
(scm_specialize_port_encoding_x, scm_i_set_port_encoding_x): Lock
while preparing iconv descriptors.
(scm_port_acquire_iconv_descriptors)
(scm_port_release_iconv_descriptors): New functions, which replace
scm_i_port_iconv_descriptors.
(scm_port_decode_char): Lock around iconv operations.
(port_clear_stream_start_for_bom_write): Acquire iconv descriptors
before checking precise_encoding, to make sure precise_encoding is
initialized.
* libguile/print.c (display_string_using_iconv): Adapt to use the new
interface to get iconv descriptors from a port.
Diffstat (limited to 'libguile/print.c')
-rw-r--r-- | libguile/print.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/libguile/print.c b/libguile/print.c index 562057722..84c9455b3 100644 --- a/libguile/print.c +++ b/libguile/print.c @@ -24,7 +24,6 @@ #endif #include <errno.h> -#include <iconv.h> #include <stdio.h> #include <assert.h> @@ -1026,9 +1025,7 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len, scm_t_string_failed_conversion_handler strategy) { size_t printed; - scm_t_iconv_descriptors *id; - - id = scm_i_port_iconv_descriptors (port); + iconv_t output_cd; printed = 0; @@ -1057,8 +1054,9 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len, output = encoded_output; output_left = sizeof (encoded_output); - done = iconv (id->output_cd, &input, &input_left, - &output, &output_left); + scm_port_acquire_iconv_descriptors (port, NULL, &output_cd); + done = iconv (output_cd, &input, &input_left, &output, &output_left); + scm_port_release_iconv_descriptors (port); output_len = sizeof (encoded_output) - output_left; @@ -1067,7 +1065,9 @@ display_string_using_iconv (const void *str, int narrow_p, size_t len, int errno_save = errno; /* Reset the `iconv' state. */ - iconv (id->output_cd, NULL, NULL, NULL, NULL); + scm_port_acquire_iconv_descriptors (port, NULL, &output_cd); + iconv (output_cd, NULL, NULL, NULL, NULL); + scm_port_release_iconv_descriptors (port); /* Print the OUTPUT_LEN bytes successfully converted. */ scm_lfwrite (encoded_output, output_len, port); |