[Python-checkins] python/dist/src/Python thread.c,2.53,2.54

tim_one at users.sourceforge.net tim_one at users.sourceforge.net
Sun Oct 10 03:58:49 CEST 2004


Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22438/Python

Modified Files:
	thread.c 
Log Message:
find_key():  This routine wasn't thread-correct, and accounts for the
release-build failures noted in bug 1041645.

This is a critical bugfix.  I'm not going to backport it, though (no time).


Index: thread.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/thread.c,v
retrieving revision 2.53
retrieving revision 2.54
diff -u -d -r2.53 -r2.54
--- thread.c	9 Oct 2004 22:33:09 -0000	2.53
+++ thread.c	10 Oct 2004 01:58:44 -0000	2.54
@@ -209,6 +209,15 @@
  * So when value==NULL, this acts like a pure lookup routine, and when
  * value!=NULL, this acts like dict.setdefault(), returning an existing
  * mapping if one exists, else creating a new mapping.
+ *
+ * Caution:  this used to be too clever, trying to hold keymutex only
+ * around the "p->next = keyhead; keyhead = p" pair.  That allowed
+ * another thread to mutate the list, via key deletion, concurrent with
+ * find_key() crawling over the list.  Hilarity ensued.  For example, when
+ * the for-loop here does "p = p->next", p could end up pointing at a
+ * record that PyThread_delete_key_value() was concurrently free()'ing.
+ * That could lead to anything, from failing to find a key that exists, to
+ * segfaults.  Now we lock the whole routine.
  */
 static struct key *
 find_key(int key, void *value)
@@ -216,22 +225,25 @@
 	struct key *p;
 	long id = PyThread_get_thread_ident();
 
+	PyThread_acquire_lock(keymutex, 1);
 	for (p = keyhead; p != NULL; p = p->next) {
 		if (p->id == id && p->key == key)
-			return p;
+			goto Done;
+	}
+	if (value == NULL) {
+		assert(p == NULL);
+		goto Done;
 	}
-	if (value == NULL)
-		return NULL;
 	p = (struct key *)malloc(sizeof(struct key));
 	if (p != NULL) {
 		p->id = id;
 		p->key = key;
 		p->value = value;
-		PyThread_acquire_lock(keymutex, 1);
 		p->next = keyhead;
 		keyhead = p;
-		PyThread_release_lock(keymutex);
 	}
+ Done:
+	PyThread_release_lock(keymutex);
 	return p;
 }
 



More information about the Python-checkins mailing list