| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,11 @@ What's New in Python 2.4 beta 1? | |||
| 12 | 12 | Core and builtins | |
| 13 | 13 | ----------------- | |
| 14 | 14 | ||
| 15 | + - The internal portable implementation of thread-local storage (TLS), used | ||
| 16 | + by the ``PyGILState_Ensure()``/``PyGILState_Release()`` API, was not | ||
| 17 | + thread-correct. This could lead to a variety of problems, up to and | ||
| 18 | + including segfaults. See bug 1041645 for an example. | ||
| 19 | + | ||
| 15 | 20 | - Added a command line option, -m module, which searches sys.path for the | |
| 16 | 21 | module and then runs it. (Contributed by Nick Coghlan.) | |
| 17 | 22 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -209,29 +209,41 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ | |||
| 209 | 209 | * So when value==NULL, this acts like a pure lookup routine, and when | |
| 210 | 210 | * value!=NULL, this acts like dict.setdefault(), returning an existing | |
| 211 | 211 | * mapping if one exists, else creating a new mapping. | |
| 212 | + * | ||
| 213 | + * Caution: this used to be too clever, trying to hold keymutex only | ||
| 214 | + * around the "p->next = keyhead; keyhead = p" pair. That allowed | ||
| 215 | + * another thread to mutate the list, via key deletion, concurrent with | ||
| 216 | + * find_key() crawling over the list. Hilarity ensued. For example, when | ||
| 217 | + * the for-loop here does "p = p->next", p could end up pointing at a | ||
| 218 | + * record that PyThread_delete_key_value() was concurrently free()'ing. | ||
| 219 | + * That could lead to anything, from failing to find a key that exists, to | ||
| 220 | + * segfaults. Now we lock the whole routine. | ||
| 212 | 221 | */ | |
| 213 | 222 | static struct key * | |
| 214 | 223 | find_key(int key, void *value) | |
| 215 | 224 | { | |
| 216 | 225 | struct key *p; | |
| 217 | 226 | long id = PyThread_get_thread_ident(); | |
| 218 | 227 | ||
| 228 | + PyThread_acquire_lock(keymutex, 1); | ||
| 219 | 229 | for (p = keyhead; p != NULL; p = p->next) { | |
| 220 | 230 | if (p->id == id && p->key == key) | |
| 221 | - return p; | ||
| 231 | + goto Done; | ||
| 232 | + } | ||
| 233 | + if (value == NULL) { | ||
| 234 | + assert(p == NULL); | ||
| 235 | + goto Done; | ||
| 222 | 236 | } | |
| 223 | - if (value == NULL) | ||
| 224 | - return NULL; | ||
| 225 | 237 | p = (struct key *)malloc(sizeof(struct key)); | |
| 226 | 238 | if (p != NULL) { | |
| 227 | 239 | p->id = id; | |
| 228 | 240 | p->key = key; | |
| 229 | 241 | p->value = value; | |
| 230 | - PyThread_acquire_lock(keymutex, 1); | ||
| 231 | 242 | p->next = keyhead; | |
| 232 | 243 | keyhead = p; | |
| 233 | - PyThread_release_lock(keymutex); | ||
| 234 | 244 | } | |
| 245 | + Done: | ||
| 246 | + PyThread_release_lock(keymutex); | ||
| 235 | 247 | return p; | |
| 236 | 248 | } | |
| 237 | 249 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments