| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent cb1c4c8 commit 590cebe
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,10 @@ Release date: 2014-01-05 | |||
| 10 | 10 | Core and Builtins | |
| 11 | 11 | ----------------- | |
| 12 | 12 | ||
| 13 | + - Issue #19787: PyThread_set_key_value() now always set the value. In Python | ||
| 14 | + 3.3, the function did nothing if the key already exists (if the current value | ||
| 15 | + is a non-NULL pointer). | ||
| 16 | + | ||
| 13 | 17 | - Issue #14432: Remove the thread state field from the frame structure. Fix a | |
| 14 | 18 | crash when a generator is created in a C thread that is destroyed while the | |
| 15 | 19 | generator is still used. The issue was that a generator contains a frame, and | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -168,14 +168,11 @@ set_reentrant(int reentrant) | |||
| 168 | 168 | assert(reentrant == 0 || reentrant == 1); | |
| 169 | 169 | if (reentrant) { | |
| 170 | 170 | assert(PyThread_get_key_value(tracemalloc_reentrant_key) == NULL); | |
| 171 | - PyThread_set_key_value(tracemalloc_reentrant_key, | ||
| 172 | - REENTRANT); | ||
| 171 | + PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT); | ||
| 173 | 172 | } | |
| 174 | 173 | else { | |
| 175 | - /* FIXME: PyThread_set_key_value() cannot be used to set the flag | ||
| 176 | - to zero, because it does nothing if the variable has already | ||
| 177 | - a value set. */ | ||
| 178 | - PyThread_delete_key_value(tracemalloc_reentrant_key); | ||
| 174 | + assert(PyThread_get_key_value(tracemalloc_reentrant_key) == REENTRANT); | ||
| 175 | + PyThread_set_key_value(tracemalloc_reentrant_key, NULL); | ||
| 179 | 176 | } | |
| 180 | 177 | } | |
| 181 | 178 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -723,18 +723,18 @@ _PyGILState_NoteThreadState(PyThreadState* tstate) | |||
| 723 | 723 | ||
| 724 | 724 | The only situation where you can legitimately have more than one | |
| 725 | 725 | thread state for an OS level thread is when there are multiple | |
| 726 | - interpreters, when: | ||
| 726 | + interpreters. | ||
| 727 | 727 | ||
| 728 | - a) You shouldn't really be using the PyGILState_ APIs anyway, | ||
| 729 | - and: | ||
| 728 | + You shouldn't really be using the PyGILState_ APIs anyway (see issues | ||
| 729 | + #10915 and #15751). | ||
| 730 | 730 | ||
| 731 | - b) The slightly odd way PyThread_set_key_value works (see | ||
| 732 | - comments by its implementation) means that the first thread | ||
| 733 | - state created for that given OS level thread will "win", | ||
| 734 | - which seems reasonable behaviour. | ||
| 731 | + The first thread state created for that given OS level thread will | ||
| 732 | + "win", which seems reasonable behaviour. | ||
| 735 | 733 | */ | |
| 736 | - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) | ||
| 737 | - Py_FatalError("Couldn't create autoTLSkey mapping"); | ||
| 734 | + if (PyThread_get_key_value(autoTLSkey) == NULL) { | ||
| 735 | + if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) | ||
| 736 | + Py_FatalError("Couldn't create autoTLSkey mapping"); | ||
| 737 | + } | ||
| 738 | 738 | ||
| 739 | 739 | /* PyGILState_Release must not try to delete this thread state. */ | |
| 740 | 740 | tstate->gilstate_counter = 1; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -205,7 +205,7 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ | |||
| 205 | 205 | * segfaults. Now we lock the whole routine. | |
| 206 | 206 | */ | |
| 207 | 207 | static struct key * | |
| 208 | - find_key(int key, void *value) | ||
| 208 | + find_key(int set_value, int key, void *value) | ||
| 209 | 209 | { | |
| 210 | 210 | struct key *p, *prev_p; | |
| 211 | 211 | long id = PyThread_get_thread_ident(); | |
@@ -215,8 +215,11 @@ find_key(int key, void *value) | |||
| 215 | 215 | PyThread_acquire_lock(keymutex, 1); | |
| 216 | 216 | prev_p = NULL; | |
| 217 | 217 | for (p = keyhead; p != NULL; p = p->next) { | |
| 218 | - if (p->id == id && p->key == key) | ||
| 218 | + if (p->id == id && p->key == key) { | ||
| 219 | + if (set_value) | ||
| 220 | + p->value = value; | ||
| 219 | 221 | goto Done; | |
| 222 | + } | ||
| 220 | 223 | /* Sanity check. These states should never happen but if | |
| 221 | 224 | * they do we must abort. Otherwise we'll end up spinning in | |
| 222 | 225 | * in a tight loop with the lock held. A similar check is done | |
@@ -227,7 +230,7 @@ find_key(int key, void *value) | |||
| 227 | 230 | if (p->next == keyhead) | |
| 228 | 231 | Py_FatalError("tls find_key: circular list(!)"); | |
| 229 | 232 | } | |
| 230 | - if (value == NULL) { | ||
| 233 | + if (!set_value && value == NULL) { | ||
| 231 | 234 | assert(p == NULL); | |
| 232 | 235 | goto Done; | |
| 233 | 236 | } | |
@@ -279,19 +282,12 @@ PyThread_delete_key(int key) | |||
| 279 | 282 | PyThread_release_lock(keymutex); | |
| 280 | 283 | } | |
| 281 | 284 | ||
| 282 | - /* Confusing: If the current thread has an association for key, | ||
| 283 | - * value is ignored, and 0 is returned. Else an attempt is made to create | ||
| 284 | - * an association of key to value for the current thread. 0 is returned | ||
| 285 | - * if that succeeds, but -1 is returned if there's not enough memory | ||
| 286 | - * to create the association. value must not be NULL. | ||
| 287 | - */ | ||
| 288 | 285 | int | |
| 289 | 286 | PyThread_set_key_value(int key, void *value) | |
| 290 | 287 | { | |
| 291 | 288 | struct key *p; | |
| 292 | 289 | ||
| 293 | - assert(value != NULL); | ||
| 294 | - p = find_key(key, value); | ||
| 290 | + p = find_key(1, key, value); | ||
| 295 | 291 | if (p == NULL) | |
| 296 | 292 | return -1; | |
| 297 | 293 | else | |
@@ -304,7 +300,7 @@ PyThread_set_key_value(int key, void *value) | |||
| 304 | 300 | void * | |
| 305 | 301 | PyThread_get_key_value(int key) | |
| 306 | 302 | { | |
| 307 | - struct key *p = find_key(key, NULL); | ||
| 303 | + struct key *p = find_key(0, key, NULL); | ||
| 308 | 304 | ||
| 309 | 305 | if (p == NULL) | |
| 310 | 306 | return NULL; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -389,20 +389,11 @@ PyThread_delete_key(int key) | |||
| 389 | 389 | TlsFree(key); | |
| 390 | 390 | } | |
| 391 | 391 | ||
| 392 | - /* We must be careful to emulate the strange semantics implemented in thread.c, | ||
| 393 | - * where the value is only set if it hasn't been set before. | ||
| 394 | - */ | ||
| 395 | 392 | int | |
| 396 | 393 | PyThread_set_key_value(int key, void *value) | |
| 397 | 394 | { | |
| 398 | 395 | BOOL ok; | |
| 399 | - void *oldvalue; | ||
| 400 | 396 | ||
| 401 | - assert(value != NULL); | ||
| 402 | - oldvalue = TlsGetValue(key); | ||
| 403 | - if (oldvalue != NULL) | ||
| 404 | - /* ignore value if already set */ | ||
| 405 | - return 0; | ||
| 406 | 397 | ok = TlsSetValue(key, value); | |
| 407 | 398 | if (!ok) | |
| 408 | 399 | return -1; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -627,9 +627,6 @@ int | |||
| 627 | 627 | PyThread_set_key_value(int key, void *value) | |
| 628 | 628 | { | |
| 629 | 629 | int fail; | |
| 630 | - void *oldValue = pthread_getspecific(key); | ||
| 631 | - if (oldValue != NULL) | ||
| 632 | - return 0; | ||
| 633 | 630 | fail = pthread_setspecific(key, value); | |
| 634 | 631 | return fail ? -1 : 0; | |
| 635 | 632 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments