c50d1616fc9f52b6cdb9f109865d4f7044e96a0f
angie
  Thu Dec 8 23:45:40 2011 -0800
Feature #2823 (VCF+tabix track handler): found & fixed more non-reentrant code that can lead to race conditions when multiple VCF
tracks are loaded in parallel.  More than 1000 tries have been
successful compared to 5 or 6 failures per 1000 tries before.

diff --git src/hg/lib/pgSnp.c src/hg/lib/pgSnp.c
index 1283a52..815bdd9 100644
--- src/hg/lib/pgSnp.c
+++ src/hg/lib/pgSnp.c
@@ -688,36 +688,31 @@
     lineFileAbort(lf, "invalid allele frequency, %s with count of %d", row[5], item->alleleCount);
 /* scores, comma separated list of numbers with above # of items */
 item->alleleScores = cloneString(row[6]);
 safef(pattern, sizeof(pattern), "^[0-9.]+(,[0-9.]+){%d}$", item->alleleCount - 1);
 if (! regexMatchNoCase(row[6], pattern))
     lineFileAbort(lf, "invalid allele scores, %s with count of %d", row[6], item->alleleCount);
 return item;
 }
 
 #define VCF_MAX_ALLELE_LEN 80
 
 static char *alleleCountsFromVcfRecord(struct vcfRecord *rec, int alDescCount)
 /* Build up comma-sep list of per-allele counts, if available, up to alDescCount
  * which may be less than rec->alleleCount: */
 {
-static struct dyString *dy = NULL;
-if (dy == NULL)
-    dy = dyStringNew(0);
-else
-    dyStringClear(dy);
-dyStringClear(dy);
+struct dyString *dy = dyStringNew(0);
 int alCounts[VCF_MAX_ALLELE_LEN];
 boolean gotTotalCount = FALSE, gotAltCounts = FALSE;
 int i;
 for (i = 0;  i < rec->infoCount;  i++)
     if (sameString(rec->infoElements[i].key, "AN"))
 	{
 	gotTotalCount = TRUE;
 	// Set ref allele to total count, subtract alt counts below.
 	alCounts[0] = rec->infoElements[i].values[0].datInt;
 	break;
 	}
 for (i = 0;  i < rec->infoCount;  i++)
     if (sameString(rec->infoElements[i].key, "AC"))
 	{
 	if (rec->infoElements[i].count > 0)
@@ -753,31 +748,31 @@
     for (i = 0;  i < alDescCount;  i++)
 	alCounts[i] = 0;
     for (i = 0;  i < rec->file->genotypeCount;  i++)
 	{
 	struct vcfGenotype *gt = &(rec->genotypes[i]);
 	if (gt == NULL)
 	    uglyf("i=%d gt=NULL wtf?\n", i);
 	alCounts[gt->hapIxA]++;
 	if (! gt->isHaploid)
 	    alCounts[gt->hapIxB]++;
 	}
     dyStringPrintf(dy, "%d", alCounts[0]);
     for (i = 1;  i < alDescCount;  i++)
 	dyStringPrintf(dy, ",%d", alCounts[i]);
     }
-return cloneStringZ(dy->string, dy->stringSize+1);
+return dyStringCannibalize(&dy);
 }
 
 struct pgSnp *pgSnpFromVcfRecord(struct vcfRecord *rec)
 /* Convert VCF rec to pgSnp; don't free rec->file (vcfFile) until
  * you're done with pgSnp because pgSnp points to rec->chrom. */
 {
 struct dyString *dy = dyStringNew(0);
 struct pgSnp *pgs;
 AllocVar(pgs);
 pgs->chrom = rec->chrom;
 pgs->chromStart = rec->chromStart;
 pgs->chromEnd = rec->chromEnd;
 // Build up slash-separated allele string from rec->alleles, starting with ref allele:
 dyStringAppend(dy, rec->alleles[0]);
 int alCount = rec->alleleCount, i;