summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2011-02-10 21:40:25 +0100
committerAndy Wingo <wingo@pobox.com>2011-02-10 23:16:52 +0100
commitb7b4aef97cc4b84e1f5ff4707f4a39f1b637544d (patch)
tree544e9102f16013ae605ef49e1d425cacb900ec76
parente8065fe452208b82cd36f9437d55760d132fde32 (diff)
downloadguile-b7b4aef97cc4b84e1f5ff4707f4a39f1b637544d.tar.gz
fix potential concurrency bugs in port-for-each
* libguile/ports.c (scm_c_port_for_each): Simplify to avoid concurrency- and gc-related bugs.
-rw-r--r--libguile/ports.c39
1 files changed, 12 insertions, 27 deletions
diff --git a/libguile/ports.c b/libguile/ports.c
index 1da6a833b..587998a01 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -867,44 +867,29 @@ SCM_DEFINE (scm_close_output_port, "close-output-port", 1, 0, 0,
#undef FUNC_NAME
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;
- scm_c_vector_set_x (result, *i, key);
- (*i)++;
-
- return result;
+ return scm_cons (key, result);
}
void
scm_c_port_for_each (void (*proc)(void *data, SCM p), void *data)
{
- int i = 0;
- size_t n;
SCM ports;
- /* Even without pre-emptive multithreading, running arbitrary code
- while scanning the port table is unsafe because the port table
- 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);
-
+ /* Copy out the port table as a list so that we get strong references
+ to all the values. */
scm_i_pthread_mutex_lock (&scm_i_port_table_mutex);
- ports = scm_internal_hash_fold (scm_i_collect_keys_in_vector, &i,
- ports, scm_i_port_weak_hash);
+ ports = scm_internal_hash_fold (collect_keys, NULL,
+ SCM_EOL, scm_i_port_weak_hash);
scm_i_pthread_mutex_unlock (&scm_i_port_table_mutex);
- for (i = 0; i < n; i++) {
- SCM p = SCM_SIMPLE_VECTOR_REF (ports, i);
- if (SCM_PORTP (p))
- proc (data, p);
- }
-
- scm_remember_upto_here_1 (ports);
+ for (; scm_is_pair (ports); ports = scm_cdr (ports))
+ {
+ SCM p = scm_car (ports);
+ if (SCM_PORTP (p))
+ proc (data, p);
+ }
}
SCM_DEFINE (scm_port_for_each, "port-for-each", 1, 0, 0,