1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-30 06:50:31 +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:
Andy Wingo 2011-02-10 21:40:25 +01:00
parent e8065fe452
commit b7b4aef97c

View file

@ -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); {
if (SCM_PORTP (p)) SCM p = scm_car (ports);
proc (data, p); if (SCM_PORTP (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,