diff options
author | David Mitchell <davem@iabyn.com> | 2019-02-18 09:29:29 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2019-02-19 13:28:12 +0000 |
commit | 04912be77a628a4643d16a99a332a73853926079 (patch) | |
tree | 78057c2aed6b7fb0a330616a8c235cd6c5e73346 /util.c | |
parent | 61d4c87c940fea028f08f27addc275b469320fda (diff) | |
download | perl-04912be77a628a4643d16a99a332a73853926079.tar.gz |
fix thread issue with PERL_GLOBAL_STRUCT
The MY_CXT subsystem allows per-thread pseudo-static data storage.
Part of the implementation for this involves each XS module being
assigned a unique index in its my_cxt_index static var when first
loaded.
Because PERL_GLOBAL_STRUCT bans any static vars, under those builds
there is instead a table which maps the MY_CXT_KEY identifying string to
index.
Unfortunately, this table was allocated per-interpreter rather than
globally, meaning if multiple threads tried to load the same XS module,
crashes could ensue.
This manifested itself in failures in
ext/XS-APItest/t/keyword_plugin_threads.t
The fix is relatively straightforward: allocate PL_my_cxt_keys globally
rather than per-interpreter.
Also record the size of this struct in a new var, PL_my_cxt_keys_size,
rather than doing double duty on PL_my_cxt_size.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 31 |
1 files changed, 27 insertions, 4 deletions
@@ -5290,6 +5290,33 @@ Perl_my_cxt_init(pTHX_ const char *my_cxt_key, size_t size) if (index == -1) /* this module hasn't been allocated an index yet */ index = PL_my_cxt_index++; + + /* Store the index in a global MY_CXT_KEY string to index mapping + * table. This emulates the perl-module static my_cxt_index var on + * builds which don't allow static vars */ + if (PL_my_cxt_keys_size <= index) { + int old_size = PL_my_cxt_keys_size; + int i; + if (PL_my_cxt_keys_size) { + IV new_size = PL_my_cxt_keys_size; + while (new_size <= index) + new_size *= 2; + PL_my_cxt_keys = (const char **)PerlMemShared_realloc( + PL_my_cxt_keys, + new_size * sizeof(const char *)); + PL_my_cxt_keys_size = new_size; + } + else { + PL_my_cxt_keys_size = 16; + PL_my_cxt_keys = (const char **)PerlMemShared_malloc( + PL_my_cxt_keys_size * sizeof(const char *)); + } + for (i = old_size; i < PL_my_cxt_keys_size; i++) { + PL_my_cxt_keys[i] = 0; + } + } + PL_my_cxt_keys[index] = my_cxt_key; + MUTEX_UNLOCK(&PL_my_ctx_mutex); } @@ -5302,20 +5329,16 @@ Perl_my_cxt_init(pTHX_ const char *my_cxt_key, size_t size) while (new_size <= index) new_size *= 2; Renew(PL_my_cxt_list, new_size, void *); - Renew(PL_my_cxt_keys, new_size, const char *); PL_my_cxt_size = new_size; } else { PL_my_cxt_size = 16; Newx(PL_my_cxt_list, PL_my_cxt_size, void *); - Newx(PL_my_cxt_keys, PL_my_cxt_size, const char *); } for (i = old_size; i < PL_my_cxt_size; i++) { - PL_my_cxt_keys[i] = 0; PL_my_cxt_list[i] = 0; } } - PL_my_cxt_keys[index] = my_cxt_key; /* newSV() allocates one more than needed */ p = (void*)SvPVX(newSV(size-1)); PL_my_cxt_list[index] = p; |