mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-30 15:00:21 +02:00
fix potential concurrency bugs in port-for-each
* libguile/ports.c (scm_c_port_for_each): Simplify to avoid concurrency- and gc-related bugs.
This commit is contained in:
parent
e8065fe452
commit
b7b4aef97c
1 changed files with 12 additions and 27 deletions
|
@ -867,44 +867,29 @@ SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
scm_i_collect_keys_in_vector (void *closure, SCM key, SCM value, SCM result)
|
collect_keys (void *unused, SCM key, SCM value, SCM result)
|
||||||
{
|
{
|
||||||
int *i = (int*) closure;
|
return scm_cons (key, result);
|
||||||
scm_c_vector_set_x (result, *i, key);
|
|
||||||
(*i)++;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
|
scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
size_t n;
|
|
||||||
SCM ports;
|
SCM ports;
|
||||||
|
|
||||||
/* Even without pre-emptive multithreading, running arbitrary code
|
/* Copy out the port table as a list so that we get strong references
|
||||||
while scanning the port table is unsafe because the port table
|
to all the values. */
|
||||||
can change arbitrarily (from a GC, for example). So we first
|
|
||||||
collect the ports into a vector. -mvo */
|
|
||||||
|
|
||||||
scm_i_scm_pthread_mutex_lock (&scm_i_port_table_mutex);
|
|
||||||
n = SCM_HASHTABLE_N_ITEMS (scm_i_port_weak_hash);
|
|
||||||
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
|
|
||||||
ports = scm_c_make_vector (n, SCM_BOOL_F);
|
|
||||||
|
|
||||||
scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
|
scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
|
||||||
ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
|
ports = scm_internal_hash_fold (collect_keys, NULL,
|
||||||
ports, scm_i_port_weak_hash);
|
SCM_EOL, scm_i_port_weak_hash);
|
||||||
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
|
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (; scm_is_pair (ports); ports = scm_cdr (ports))
|
||||||
SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
|
{
|
||||||
|
SCM p = scm_car (ports);
|
||||||
if (SCM_PORTP (p))
|
if (SCM_PORTP (p))
|
||||||
proc (data, p);
|
proc (data, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
scm_remember_upto_here_1 (ports);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
|
SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue