2015-07-30
2015-07-30 16:33:49 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
d5a5bf0d38daaad6070cb0852eb0a7d34a54f73e
(50 lines)
(+39/-11)
[
Show
| Annotate
]
Branch: 8.0
Pike.identify_cycle: Fixed global variable overwrite.
Pike.identify_cycle() uses a mapping internally, and insert into
mappings can call Pike code (via LFUN:__hash()), which could
have a different thread also start messing with the same variables.
This fixes the multi-thread case, but there's still a problem if it
starts to recurse (ie LFUN::__hash() calling Pike.identify_cycle()
or Pike_count_memory()).
4580:
#define MC_WQ_START_SIZE 1024
+ static IMUTEX_T mc_mutex;
+
PMOD_EXPORT int mc_pass;
PMOD_EXPORT size_t mc_counted_bytes;
4691:
PTR_HASH_ALLOC_FILL_PAGES (mc_marker, 2)
+ static void start_mc(void)
+ {
+ LOCK_IMUTEX(&mc_mutex);
+ init_mc_marker_hash();
+ }
+
+ static void stop_mc(void)
+ {
+ exit_mc_marker_hash();
+ UNLOCK_IMUTEX(&mc_mutex);
+ }
+
static struct mc_marker *my_make_mc_marker (void *thing,
visit_thing_fn *visit_fn,
void *extra)
5622:
Pike_sp[-args].u.integer;
}
- init_mc_marker_hash();
+ start_mc();
if (TYPEOF(pike_cycle_depth_str) == PIKE_T_FREE) {
SET_SVAL_TYPE(pike_cycle_depth_str, T_STRING);
5632:
assert (mc_work_queue == NULL);
mc_work_queue = malloc (MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));
if (!mc_work_queue) {
- exit_mc_marker_hash();
+ stop_mc();
SIMPLE_OUT_OF_MEMORY_ERROR ("Pike.count_memory",
MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));
}
5657:
continue;
else if (!REFCOUNTED_TYPE(TYPEOF(*s))) {
- exit_mc_marker_hash();
+
free (mc_work_queue + 1);
mc_work_queue = NULL;
-
+ stop_mc();
SIMPLE_ARG_TYPE_ERROR (
"count_memory", i + args + 1,
"array|multiset|mapping|object|program|string|type|int");
5669:
if (TYPEOF(*s) == T_FUNCTION) {
struct svalue s2;
if (!(s2.u.program = program_from_function (s))) {
- exit_mc_marker_hash();
+
free (mc_work_queue + 1);
mc_work_queue = NULL;
-
+ stop_mc();
SIMPLE_ARG_TYPE_ERROR (
"count_memory", i + args + 1,
"array|multiset|mapping|object|program|string|type|int");
5693:
if (!mc_block_pike_cycle_depth && TYPEOF(*s) == T_OBJECT) {
int cycle_depth = mc_cycle_depth_from_obj (s->u.object);
if (TYPEOF(throw_value) != PIKE_T_FREE) {
- exit_mc_marker_hash();
+
free (mc_work_queue + 1);
mc_work_queue = NULL;
-
+ stop_mc();
throw_severity = THROW_ERROR;
pike_throw();
}
5822:
}
if (TYPEOF(throw_value) != PIKE_T_FREE) {
- exit_mc_marker_hash();
+
free (mc_work_queue + 1);
mc_work_queue = NULL;
-
+ stop_mc();
throw_severity = THROW_ERROR;
pike_throw();
}
6069: Inside #if defined(DO_PIKE_CLEANUP)
remove_mc_marker (mc_marker_hash_table[e]->thing);
}
#endif
- exit_mc_marker_hash();
+
assert (mc_wq_used == 1);
free (mc_work_queue + 1);
mc_work_queue = NULL;
-
+ stop_mc();
pop_n_elems (args);
push_ulongest (return_count ? count_internal : mc_counted_bytes);
6178:
SET_SVAL_TYPE(*s, T_OBJECT);
}
- init_mc_marker_hash();
+ start_mc();
if (TYPEOF(pike_cycle_depth_str) == PIKE_T_FREE) {
SET_SVAL_TYPE(pike_cycle_depth_str, T_STRING);
6188:
assert (mc_work_queue == NULL);
mc_work_queue = malloc (MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));
if (!mc_work_queue) {
- exit_mc_marker_hash();
+ stop_mc();
SIMPLE_OUT_OF_MEMORY_ERROR ("Pike.count_memory",
MC_WQ_START_SIZE * sizeof (mc_work_queue[0]));
}
6229:
mc_ref_from = (void *) (ptrdiff_t) -1;
#endif
- exit_mc_marker_hash();
- free (mc_work_queue + 1);
+ /* NB: 1-based indexing in mc_work_queue. */
+ mc_work_queue++;
+ free(mc_work_queue);
mc_work_queue = NULL;
visit_enter = NULL;
6257:
free_mapping(identify_loop_reverse);
+ stop_mc();
+
if (!k) {
push_undefined();
} else {
6267:
f_reverse(1);
}
}
+
+ void init_mc(void)
+ {
+ init_interleave_mutex(&mc_mutex);
+ }
+
+ void exit_mc(void)
+ {
+ exit_interleave_mutex(&mc_mutex);
+ }