Branch: Tag:

2015-07-30

2015-07-30 16:33:49 by Henrik Grubbström (Grubba) <grubba@grubba.org>

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); + }