mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-16 16:50:21 +02:00
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.
This commit is contained in:
parent
c95a19376b
commit
6bf7ec0c9c
3 changed files with 128 additions and 130 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue